aboutsummaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2014-11-25 21:00:58 +0000
committerEd Maste <emaste@FreeBSD.org>2014-11-25 21:00:58 +0000
commit0cac4ca3916ac24ab6139d03cbfd18db9e715bfe (patch)
treec94307da318be46e5aeea1a325c1e91749506e4f /source
parent03b99097822ca3ac69252d9afae716a584ed56c4 (diff)
downloadsrc-0cac4ca3916ac24ab6139d03cbfd18db9e715bfe.tar.gz
src-0cac4ca3916ac24ab6139d03cbfd18db9e715bfe.zip
Import LLDB as of upstream SVN r216948 (git 50f7fe44)vendor/lldb/lldb-r216948
This corresponds with the branchpoint for the 3.5 release. A number of files not required for the FreeBSD build have been removed. Sponsored by: DARPA, AFRL
Notes
Notes: svn path=/vendor/lldb/dist/; revision=275072 svn path=/vendor/lldb/lldb-r216948/; revision=275074; tag=vendor/lldb/lldb-r216948
Diffstat (limited to 'source')
-rw-r--r--source/API/SBAddress.cpp8
-rw-r--r--source/API/SBBreakpoint.cpp117
-rw-r--r--source/API/SBBreakpointLocation.cpp57
-rw-r--r--source/API/SBBroadcaster.cpp18
-rw-r--r--source/API/SBCommandInterpreter.cpp58
-rw-r--r--source/API/SBCommandReturnObject.cpp14
-rw-r--r--source/API/SBCommunication.cpp52
-rw-r--r--source/API/SBCompileUnit.cpp31
-rw-r--r--source/API/SBData.cpp182
-rw-r--r--source/API/SBDebugger.cpp153
-rw-r--r--source/API/SBDeclaration.cpp21
-rw-r--r--source/API/SBError.cpp12
-rw-r--r--source/API/SBEvent.cpp19
-rw-r--r--source/API/SBExpressionOptions.cpp61
-rw-r--r--source/API/SBFileSpec.cpp30
-rw-r--r--source/API/SBFileSpecList.cpp3
-rw-r--r--source/API/SBFrame.cpp169
-rw-r--r--source/API/SBFunction.cpp12
-rw-r--r--source/API/SBHostOS.cpp26
-rw-r--r--source/API/SBLineEntry.cpp20
-rw-r--r--source/API/SBListener.cpp38
-rw-r--r--source/API/SBModule.cpp49
-rw-r--r--source/API/SBProcess.cpp348
-rw-r--r--source/API/SBQueue.cpp136
-rw-r--r--source/API/SBQueueItem.cpp60
-rw-r--r--source/API/SBStream.cpp2
-rw-r--r--source/API/SBSymbol.cpp6
-rw-r--r--source/API/SBSymbolContext.cpp28
-rw-r--r--source/API/SBTarget.cpp453
-rw-r--r--source/API/SBThread.cpp374
-rw-r--r--source/API/SBType.cpp32
-rw-r--r--source/API/SBTypeEnumMember.cpp192
-rw-r--r--source/API/SBUnixSignals.cpp199
-rw-r--r--source/API/SBValue.cpp406
-rw-r--r--source/API/SBValueList.cpp16
-rw-r--r--source/API/SBWatchpoint.cpp13
-rw-r--r--source/Breakpoint/Breakpoint.cpp2
-rw-r--r--source/Breakpoint/BreakpointID.cpp2
-rw-r--r--source/Breakpoint/BreakpointList.cpp2
-rw-r--r--source/Breakpoint/BreakpointLocation.cpp19
-rw-r--r--source/Breakpoint/BreakpointLocationList.cpp2
-rw-r--r--source/Breakpoint/BreakpointOptions.cpp2
-rw-r--r--source/Breakpoint/BreakpointResolverName.cpp4
-rw-r--r--source/Breakpoint/BreakpointSite.cpp11
-rw-r--r--source/Breakpoint/BreakpointSiteList.cpp2
-rw-r--r--source/Breakpoint/WatchpointList.cpp2
-rw-r--r--source/Commands/CommandCompletions.cpp31
-rw-r--r--source/Commands/CommandObjectArgs.cpp14
-rw-r--r--source/Commands/CommandObjectBreakpoint.cpp95
-rw-r--r--source/Commands/CommandObjectBreakpointCommand.cpp151
-rw-r--r--source/Commands/CommandObjectCommands.cpp41
-rw-r--r--source/Commands/CommandObjectDisassemble.cpp197
-rw-r--r--source/Commands/CommandObjectExpression.cpp94
-rw-r--r--source/Commands/CommandObjectExpression.h3
-rw-r--r--source/Commands/CommandObjectFrame.cpp10
-rw-r--r--source/Commands/CommandObjectHelp.cpp6
-rw-r--r--source/Commands/CommandObjectLog.cpp20
-rw-r--r--source/Commands/CommandObjectMemory.cpp38
-rw-r--r--source/Commands/CommandObjectPlatform.cpp89
-rw-r--r--source/Commands/CommandObjectProcess.cpp144
-rw-r--r--source/Commands/CommandObjectQuit.cpp2
-rw-r--r--source/Commands/CommandObjectRegister.cpp11
-rw-r--r--source/Commands/CommandObjectSettings.cpp9
-rw-r--r--source/Commands/CommandObjectSource.cpp30
-rw-r--r--source/Commands/CommandObjectTarget.cpp749
-rw-r--r--source/Commands/CommandObjectThread.cpp303
-rw-r--r--source/Commands/CommandObjectType.cpp190
-rw-r--r--source/Commands/CommandObjectWatchpoint.cpp46
-rw-r--r--source/Commands/CommandObjectWatchpointCommand.cpp10
-rw-r--r--source/Core/Address.cpp2
-rw-r--r--source/Core/AddressRange.cpp5
-rw-r--r--source/Core/AddressResolverName.cpp2
-rw-r--r--source/Core/ArchSpec.cpp190
-rw-r--r--source/Core/Broadcaster.cpp32
-rw-r--r--source/Core/Communication.cpp16
-rw-r--r--source/Core/ConnectionFileDescriptor.cpp1449
-rw-r--r--source/Core/ConnectionMachPort.cpp4
-rw-r--r--source/Core/ConnectionSharedMemory.cpp12
-rw-r--r--source/Core/ConstString.cpp5
-rw-r--r--source/Core/DataBufferHeap.cpp6
-rw-r--r--source/Core/DataBufferMemoryMap.cpp94
-rw-r--r--source/Core/DataExtractor.cpp55
-rw-r--r--source/Core/Debugger.cpp469
-rw-r--r--source/Core/EmulateInstruction.cpp16
-rw-r--r--source/Core/Error.cpp31
-rw-r--r--source/Core/Event.cpp17
-rw-r--r--source/Core/FastDemangle.cpp2203
-rw-r--r--source/Core/IOHandler.cpp576
-rw-r--r--source/Core/Language.cpp4
-rw-r--r--source/Core/Listener.cpp68
-rw-r--r--source/Core/Log.cpp2
-rw-r--r--source/Core/Mangled.cpp29
-rw-r--r--source/Core/Module.cpp199
-rw-r--r--source/Core/ModuleList.cpp59
-rw-r--r--source/Core/Opcode.cpp2
-rw-r--r--source/Core/PluginManager.cpp198
-rw-r--r--source/Core/RegularExpression.cpp8
-rw-r--r--source/Core/Scalar.cpp22
-rw-r--r--source/Core/SearchFilter.cpp2
-rw-r--r--source/Core/Section.cpp36
-rw-r--r--source/Core/SourceManager.cpp2
-rw-r--r--source/Core/Stream.cpp4
-rw-r--r--source/Core/StructuredData.cpp429
-rw-r--r--source/Core/Value.cpp98
-rw-r--r--source/Core/ValueObject.cpp145
-rw-r--r--source/Core/ValueObjectChild.cpp52
-rw-r--r--source/Core/ValueObjectConstResult.cpp6
-rw-r--r--source/Core/ValueObjectConstResultImpl.cpp6
-rw-r--r--source/Core/ValueObjectDynamicValue.cpp64
-rw-r--r--source/Core/ValueObjectMemory.cpp8
-rw-r--r--source/Core/ValueObjectRegister.cpp6
-rw-r--r--source/Core/ValueObjectSyntheticFilter.cpp6
-rw-r--r--source/Core/ValueObjectVariable.cpp9
-rw-r--r--source/DataFormatters/CF.cpp6
-rw-r--r--source/DataFormatters/CXXFormatterFunctions.cpp116
-rw-r--r--source/DataFormatters/Cocoa.cpp6
-rw-r--r--source/DataFormatters/FormatManager.cpp149
-rw-r--r--source/DataFormatters/LibCxx.cpp10
-rw-r--r--source/DataFormatters/LibCxxList.cpp56
-rw-r--r--source/DataFormatters/LibCxxMap.cpp10
-rw-r--r--source/DataFormatters/LibCxxUnorderedMap.cpp7
-rw-r--r--source/DataFormatters/LibStdcpp.cpp2
-rw-r--r--source/DataFormatters/NSArray.cpp384
-rw-r--r--source/DataFormatters/NSDictionary.cpp12
-rw-r--r--source/DataFormatters/NSSet.cpp6
-rw-r--r--source/DataFormatters/TypeFormat.cpp28
-rw-r--r--source/DataFormatters/TypeSummary.cpp23
-rw-r--r--source/DataFormatters/TypeSynthetic.cpp4
-rw-r--r--source/DataFormatters/ValueObjectPrinter.cpp10
-rw-r--r--source/Expression/ASTResultSynthesizer.cpp218
-rw-r--r--source/Expression/ASTStructExtractor.cpp64
-rw-r--r--source/Expression/ClangASTSource.cpp1010
-rw-r--r--source/Expression/ClangExpressionDeclMap.cpp866
-rw-r--r--source/Expression/ClangExpressionParser.cpp390
-rw-r--r--source/Expression/ClangExpressionVariable.cpp19
-rw-r--r--source/Expression/ClangFunction.cpp88
-rw-r--r--source/Expression/ClangUserExpression.cpp541
-rw-r--r--source/Expression/ClangUtilityFunction.cpp37
-rw-r--r--source/Expression/DWARFExpression.cpp243
-rw-r--r--source/Expression/ExpressionSourceCode.cpp55
-rw-r--r--source/Expression/IRDynamicChecks.cpp213
-rw-r--r--source/Expression/IRExecutionUnit.cpp497
-rw-r--r--source/Expression/IRForTarget.cpp1437
-rw-r--r--source/Expression/IRInterpreter.cpp519
-rw-r--r--source/Expression/IRMemoryMap.cpp274
-rw-r--r--source/Expression/Materializer.cpp96
-rw-r--r--source/Host/common/Condition.cpp5
-rw-r--r--source/Host/common/DynamicLibrary.cpp33
-rw-r--r--source/Host/common/Editline.cpp418
-rw-r--r--source/Host/common/File.cpp39
-rw-r--r--source/Host/common/FileCache.cpp127
-rw-r--r--source/Host/common/FileSpec.cpp381
-rw-r--r--source/Host/common/Host.cpp1282
-rw-r--r--source/Host/common/HostInfoBase.cpp318
-rw-r--r--source/Host/common/IOObject.cpp14
-rw-r--r--source/Host/common/Mutex.cpp4
-rw-r--r--source/Host/common/NativeBreakpoint.cpp116
-rw-r--r--source/Host/common/NativeBreakpoint.h66
-rw-r--r--source/Host/common/NativeBreakpointList.cpp199
-rw-r--r--source/Host/common/NativeBreakpointList.h53
-rw-r--r--source/Host/common/NativeProcessProtocol.cpp412
-rw-r--r--source/Host/common/NativeProcessProtocol.h333
-rw-r--r--source/Host/common/NativeThreadProtocol.cpp97
-rw-r--r--source/Host/common/NativeThreadProtocol.h85
-rw-r--r--source/Host/common/OptionParser.cpp21
-rw-r--r--source/Host/common/Pipe.cpp171
-rw-r--r--source/Host/common/Socket.cpp662
-rw-r--r--source/Host/common/SocketAddress.cpp3
-rw-r--r--source/Host/common/SoftwareBreakpoint.cpp296
-rw-r--r--source/Host/common/SoftwareBreakpoint.h51
-rw-r--r--source/Host/common/Terminal.cpp5
-rw-r--r--source/Host/freebsd/Host.cpp102
-rw-r--r--source/Host/freebsd/HostInfoFreeBSD.cpp85
-rw-r--r--source/Host/posix/FileSystem.cpp201
-rw-r--r--source/Host/posix/HostInfoPosix.cpp193
-rw-r--r--source/Host/posix/HostProcessPosix.cpp103
-rw-r--r--source/Interpreter/Args.cpp125
-rw-r--r--source/Interpreter/CommandHistory.cpp20
-rw-r--r--source/Interpreter/CommandInterpreter.cpp195
-rw-r--r--source/Interpreter/CommandObject.cpp213
-rw-r--r--source/Interpreter/CommandObjectRegexCommand.cpp6
-rw-r--r--source/Interpreter/CommandObjectScript.cpp4
-rw-r--r--source/Interpreter/CommandOptionValidators.cpp39
-rw-r--r--source/Interpreter/CommandReturnObject.cpp20
-rw-r--r--source/Interpreter/OptionGroupArchitecture.cpp2
-rw-r--r--source/Interpreter/OptionGroupBoolean.cpp3
-rw-r--r--source/Interpreter/OptionGroupFile.cpp6
-rw-r--r--source/Interpreter/OptionGroupFormat.cpp10
-rw-r--r--source/Interpreter/OptionGroupOutputFile.cpp10
-rw-r--r--source/Interpreter/OptionGroupPlatform.cpp8
-rw-r--r--source/Interpreter/OptionGroupString.cpp3
-rw-r--r--source/Interpreter/OptionGroupUInt64.cpp3
-rw-r--r--source/Interpreter/OptionGroupUUID.cpp2
-rw-r--r--source/Interpreter/OptionGroupValueObjectDisplay.cpp26
-rw-r--r--source/Interpreter/OptionGroupVariable.cpp16
-rw-r--r--source/Interpreter/OptionGroupWatchpoint.cpp8
-rw-r--r--source/Interpreter/OptionValue.cpp68
-rw-r--r--source/Interpreter/OptionValueArch.cpp2
-rw-r--r--source/Interpreter/OptionValueArray.cpp7
-rw-r--r--source/Interpreter/OptionValueBoolean.cpp5
-rw-r--r--source/Interpreter/OptionValueDictionary.cpp14
-rw-r--r--source/Interpreter/OptionValueEnumeration.cpp2
-rw-r--r--source/Interpreter/OptionValueFileSpec.cpp3
-rw-r--r--source/Interpreter/OptionValueFormat.cpp2
-rw-r--r--source/Interpreter/OptionValueProperties.cpp37
-rw-r--r--source/Interpreter/OptionValueUUID.cpp2
-rw-r--r--source/Interpreter/Options.cpp77
-rw-r--r--source/Interpreter/Property.cpp4
-rw-r--r--source/Interpreter/PythonDataObjects.cpp24
-rw-r--r--source/Interpreter/ScriptInterpreter.cpp35
-rw-r--r--source/Interpreter/ScriptInterpreterPython.cpp378
-rw-r--r--source/Interpreter/embedded_interpreter.py4
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp13
-rw-r--r--source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp1103
-rw-r--r--source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h145
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp10
-rw-r--r--source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp554
-rw-r--r--source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h148
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp29
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp140
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h46
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp727
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h182
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp403
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h279
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp9
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp60
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp2
-rw-r--r--source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h1
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp31
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.h2
-rw-r--r--source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp719
-rw-r--r--source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h297
-rw-r--r--source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp430
-rw-r--r--source/Plugins/JITLoader/GDB/JITLoaderGDB.h104
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp6
-rw-r--r--source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp35
-rw-r--r--source/Plugins/ObjectFile/ELF/ELFHeader.cpp6
-rw-r--r--source/Plugins/ObjectFile/ELF/ELFHeader.h8
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp838
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.h55
-rw-r--r--source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp363
-rw-r--r--source/Plugins/ObjectFile/JIT/ObjectFileJIT.h142
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp66
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h2
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp216
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.h41
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp33
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp27
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp17
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h7
-rw-r--r--source/Plugins/Process/POSIX/POSIXThread.cpp120
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIX.cpp66
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIX.h19
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp318
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.h95
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp3
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h4
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp12
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h4
-rw-r--r--source/Plugins/Process/Utility/ARMDefines.h2
-rw-r--r--source/Plugins/Process/Utility/ARMUtils.h2
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.cpp18
-rw-r--r--source/Plugins/Process/Utility/FreeBSDSignals.cpp31
-rw-r--r--source/Plugins/Process/Utility/FreeBSDSignals.h28
-rw-r--r--source/Plugins/Process/Utility/HistoryThread.cpp14
-rw-r--r--source/Plugins/Process/Utility/HistoryUnwind.cpp6
-rw-r--r--source/Plugins/Process/Utility/InferiorCallPOSIX.cpp12
-rw-r--r--source/Plugins/Process/Utility/InstructionUtils.h2
-rw-r--r--source/Plugins/Process/Utility/LinuxSignals.cpp62
-rw-r--r--source/Plugins/Process/Utility/LinuxSignals.h35
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp16
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp944
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h296
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp13
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_i386.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp14
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDummy.cpp2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDummy.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp (renamed from source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp)20
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h (renamed from source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h)10
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp (renamed from source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp)15
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h (renamed from source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h)10
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp (renamed from source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp)69
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h (renamed from source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h)14
-rw-r--r--source/Plugins/Process/Utility/RegisterContextHistory.cpp2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextHistory.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp49
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp89
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_arm64.h81
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp (renamed from source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp)57
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_i386.h (renamed from source/Plugins/Process/POSIX/RegisterContextLinux_i386.h)10
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp (renamed from source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp)70
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h (renamed from source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h)14
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMemory.cpp2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMemory.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX.h (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIX.h)21
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp299
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h272
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp)3
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h)6
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp)49
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h)6
-rw-r--r--source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextThreadMemory.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContext_mips64.h (renamed from source/Plugins/Process/POSIX/RegisterContext_mips64.h)0
-rw-r--r--source/Plugins/Process/Utility/RegisterContext_x86.h (renamed from source/Plugins/Process/POSIX/RegisterContext_x86.h)14
-rw-r--r--source/Plugins/Process/Utility/RegisterInfoInterface.h49
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_arm64.h347
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_i386.h (renamed from source/Plugins/Process/POSIX/RegisterInfos_i386.h)14
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_mips64.h (renamed from source/Plugins/Process/POSIX/RegisterInfos_mips64.h)4
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_x86_64.h (renamed from source/Plugins/Process/POSIX/RegisterInfos_x86_64.h)20
-rw-r--r--source/Plugins/Process/Utility/StopInfoMachException.cpp68
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.cpp2
-rw-r--r--source/Plugins/Process/Utility/lldb-x86-register-enums.h292
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp71
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.h48
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp22
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h8
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h4
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.cpp6
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.h2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp175
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp386
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h53
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp2993
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h210
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp328
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h2
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp397
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h25
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp52
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.h10
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp94
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h9
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp53
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h3
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp94
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp5
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp55
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp34
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h10
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp16
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp5
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h16
-rw-r--r--source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp528
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h9
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp41
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h4
-rw-r--r--source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp16
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp17
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h5
-rw-r--r--source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp475
-rw-r--r--source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h5
-rw-r--r--source/Symbol/Block.cpp46
-rw-r--r--source/Symbol/ClangASTContext.cpp438
-rw-r--r--source/Symbol/ClangASTImporter.cpp178
-rw-r--r--source/Symbol/ClangASTType.cpp2158
-rw-r--r--source/Symbol/ClangExternalASTSourceCallbacks.cpp2
-rw-r--r--source/Symbol/ClangExternalASTSourceCommon.cpp2
-rw-r--r--source/Symbol/CompileUnit.cpp16
-rw-r--r--source/Symbol/DWARFCallFrameInfo.cpp62
-rw-r--r--source/Symbol/FuncUnwinders.cpp61
-rw-r--r--source/Symbol/Function.cpp46
-rw-r--r--source/Symbol/LineTable.cpp30
-rw-r--r--source/Symbol/ObjectFile.cpp115
-rw-r--r--source/Symbol/Symbol.cpp144
-rw-r--r--source/Symbol/SymbolContext.cpp108
-rw-r--r--source/Symbol/SymbolFile.cpp6
-rw-r--r--source/Symbol/SymbolVendor.cpp33
-rw-r--r--source/Symbol/Symtab.cpp80
-rw-r--r--source/Symbol/Type.cpp313
-rw-r--r--source/Symbol/TypeList.cpp43
-rw-r--r--source/Symbol/UnwindPlan.cpp25
-rw-r--r--source/Symbol/UnwindTable.cpp34
-rw-r--r--source/Symbol/Variable.cpp26
-rw-r--r--source/Target/ABI.cpp34
-rw-r--r--source/Target/FileAction.cpp95
-rw-r--r--source/Target/JITLoader.cpp38
-rw-r--r--source/Target/JITLoaderList.cpp77
-rw-r--r--source/Target/LanguageRuntime.cpp12
-rw-r--r--source/Target/Memory.cpp36
-rw-r--r--source/Target/NativeRegisterContext.cpp470
-rw-r--r--source/Target/NativeRegisterContextRegisterInfo.cpp44
-rw-r--r--source/Target/ObjCLanguageRuntime.cpp23
-rw-r--r--source/Target/PathMappingList.cpp4
-rw-r--r--source/Target/Platform.cpp103
-rw-r--r--source/Target/Process.cpp1458
-rw-r--r--source/Target/ProcessInfo.cpp138
-rw-r--r--source/Target/ProcessLaunchInfo.cpp459
-rw-r--r--source/Target/Queue.cpp15
-rw-r--r--source/Target/QueueItem.cpp85
-rw-r--r--source/Target/RegisterContext.cpp4
-rw-r--r--source/Target/SectionLoadHistory.cpp19
-rw-r--r--source/Target/SectionLoadList.cpp31
-rw-r--r--source/Target/StackFrame.cpp15
-rw-r--r--source/Target/StackFrameList.cpp4
-rw-r--r--source/Target/StackID.cpp5
-rw-r--r--source/Target/StopInfo.cpp106
-rw-r--r--source/Target/Target.cpp127
-rw-r--r--source/Target/TargetList.cpp183
-rw-r--r--source/Target/Thread.cpp335
-rw-r--r--source/Target/ThreadList.cpp11
-rw-r--r--source/Target/ThreadPlan.cpp15
-rw-r--r--source/Target/ThreadPlanBase.cpp4
-rw-r--r--source/Target/ThreadPlanCallFunction.cpp97
-rw-r--r--source/Target/ThreadPlanCallUserExpression.cpp52
-rw-r--r--source/Target/ThreadPlanRunToAddress.cpp2
-rw-r--r--source/Target/ThreadPlanShouldStopHere.cpp142
-rw-r--r--source/Target/ThreadPlanStepInRange.cpp132
-rw-r--r--source/Target/ThreadPlanStepInstruction.cpp94
-rw-r--r--source/Target/ThreadPlanStepOut.cpp179
-rw-r--r--source/Target/ThreadPlanStepOverRange.cpp58
-rw-r--r--source/Target/ThreadPlanStepRange.cpp19
-rw-r--r--source/Target/ThreadPlanStepUntil.cpp2
-rw-r--r--source/Target/ThreadPlanTracer.cpp11
-rw-r--r--source/Utility/ARM64_DWARF_Registers.cpp148
-rw-r--r--source/Utility/ARM64_DWARF_Registers.h102
-rw-r--r--source/Utility/ARM64_GCC_Registers.h92
-rw-r--r--source/Utility/ARM_DWARF_Registers.cpp2
-rw-r--r--source/Utility/PseudoTerminal.cpp9
-rw-r--r--source/Utility/SharingPtr.cpp4
-rw-r--r--source/Utility/StringExtractor.cpp31
-rw-r--r--source/Utility/StringExtractor.h5
-rw-r--r--source/Utility/StringExtractorGDBRemote.cpp6
-rw-r--r--source/Utility/StringExtractorGDBRemote.h3
-rw-r--r--source/Utility/StringLexer.cpp101
-rw-r--r--source/Utility/TimeSpecTimeout.h2
-rw-r--r--source/lldb-log.cpp5
-rw-r--r--source/lldb.cpp75
440 files changed, 39994 insertions, 14079 deletions
diff --git a/source/API/SBAddress.cpp b/source/API/SBAddress.cpp
index 799c90907634..6aec0722169f 100644
--- a/source/API/SBAddress.cpp
+++ b/source/API/SBAddress.cpp
@@ -127,13 +127,15 @@ SBAddress::GetLoadAddress (const SBTarget &target) const
addr = m_opaque_ap->GetLoadAddress (target_sp.get());
}
}
-
+
if (log)
{
if (addr == LLDB_INVALID_ADDRESS)
- log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => LLDB_INVALID_ADDRESS", target_sp.get());
+ log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => LLDB_INVALID_ADDRESS",
+ static_cast<void*>(target_sp.get()));
else
- log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => 0x%" PRIx64, target_sp.get(), addr);
+ log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => 0x%" PRIx64,
+ static_cast<void*>(target_sp.get()), addr);
}
return addr;
diff --git a/source/API/SBBreakpoint.cpp b/source/API/SBBreakpoint.cpp
index fbdc0e32f498..a950ca934c68 100644
--- a/source/API/SBBreakpoint.cpp
+++ b/source/API/SBBreakpoint.cpp
@@ -19,9 +19,12 @@
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Address.h"
+#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
@@ -121,9 +124,11 @@ SBBreakpoint::GetID () const
if (log)
{
if (break_id == LLDB_INVALID_BREAK_ID)
- log->Printf ("SBBreakpoint(%p)::GetID () => LLDB_INVALID_BREAK_ID", m_opaque_sp.get());
+ log->Printf ("SBBreakpoint(%p)::GetID () => LLDB_INVALID_BREAK_ID",
+ static_cast<void*>(m_opaque_sp.get()));
else
- log->Printf ("SBBreakpoint(%p)::GetID () => %u", m_opaque_sp.get(), break_id);
+ log->Printf ("SBBreakpoint(%p)::GetID () => %u",
+ static_cast<void*>(m_opaque_sp.get()), break_id);
}
return break_id;
@@ -133,7 +138,12 @@ SBBreakpoint::GetID () const
bool
SBBreakpoint::IsValid() const
{
- return (bool) m_opaque_sp;
+ if (!m_opaque_sp)
+ return false;
+ else if (m_opaque_sp->GetTarget().GetBreakpointByID(m_opaque_sp->GetID()))
+ return true;
+ else
+ return false;
}
void
@@ -222,7 +232,8 @@ SBBreakpoint::SetEnabled (bool enable)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::SetEnabled (enabled=%i)", m_opaque_sp.get(), enable);
+ log->Printf ("SBBreakpoint(%p)::SetEnabled (enabled=%i)",
+ static_cast<void*>(m_opaque_sp.get()), enable);
if (m_opaque_sp)
{
@@ -249,7 +260,8 @@ SBBreakpoint::SetOneShot (bool one_shot)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::SetOneShot (one_shot=%i)", m_opaque_sp.get(), one_shot);
+ log->Printf ("SBBreakpoint(%p)::SetOneShot (one_shot=%i)",
+ static_cast<void*>(m_opaque_sp.get()), one_shot);
if (m_opaque_sp)
{
@@ -288,8 +300,9 @@ SBBreakpoint::SetIgnoreCount (uint32_t count)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::SetIgnoreCount (count=%u)", m_opaque_sp.get(), count);
-
+ log->Printf ("SBBreakpoint(%p)::SetIgnoreCount (count=%u)",
+ static_cast<void*>(m_opaque_sp.get()), count);
+
if (m_opaque_sp)
{
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
@@ -330,7 +343,8 @@ SBBreakpoint::GetHitCount () const
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::GetHitCount () => %u", m_opaque_sp.get(), count);
+ log->Printf ("SBBreakpoint(%p)::GetHitCount () => %u",
+ static_cast<void*>(m_opaque_sp.get()), count);
return count;
}
@@ -347,7 +361,8 @@ SBBreakpoint::GetIgnoreCount () const
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::GetIgnoreCount () => %u", m_opaque_sp.get(), count);
+ log->Printf ("SBBreakpoint(%p)::GetIgnoreCount () => %u",
+ static_cast<void*>(m_opaque_sp.get()), count);
return count;
}
@@ -362,7 +377,8 @@ SBBreakpoint::SetThreadID (tid_t tid)
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4" PRIx64 ")", m_opaque_sp.get(), tid);
+ log->Printf ("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4" PRIx64 ")",
+ static_cast<void*>(m_opaque_sp.get()), tid);
}
@@ -378,7 +394,8 @@ SBBreakpoint::GetThreadID ()
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::GetThreadID () => 0x%4.4" PRIx64, m_opaque_sp.get(), tid);
+ log->Printf ("SBBreakpoint(%p)::GetThreadID () => 0x%4.4" PRIx64,
+ static_cast<void*>(m_opaque_sp.get()), tid);
return tid;
}
@@ -387,7 +404,8 @@ SBBreakpoint::SetThreadIndex (uint32_t index)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::SetThreadIndex (%u)", m_opaque_sp.get(), index);
+ log->Printf ("SBBreakpoint(%p)::SetThreadIndex (%u)",
+ static_cast<void*>(m_opaque_sp.get()), index);
if (m_opaque_sp)
{
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
@@ -408,18 +426,19 @@ SBBreakpoint::GetThreadIndex() const
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::GetThreadIndex () => %u", m_opaque_sp.get(), thread_idx);
+ log->Printf ("SBBreakpoint(%p)::GetThreadIndex () => %u",
+ static_cast<void*>(m_opaque_sp.get()), thread_idx);
return thread_idx;
}
-
void
SBBreakpoint::SetThreadName (const char *thread_name)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::SetThreadName (%s)", m_opaque_sp.get(), thread_name);
+ log->Printf ("SBBreakpoint(%p)::SetThreadName (%s)",
+ static_cast<void*>(m_opaque_sp.get()), thread_name);
if (m_opaque_sp)
{
@@ -441,7 +460,8 @@ SBBreakpoint::GetThreadName () const
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::GetThreadName () => %s", m_opaque_sp.get(), name);
+ log->Printf ("SBBreakpoint(%p)::GetThreadName () => %s",
+ static_cast<void*>(m_opaque_sp.get()), name);
return name;
}
@@ -451,7 +471,8 @@ SBBreakpoint::SetQueueName (const char *queue_name)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::SetQueueName (%s)", m_opaque_sp.get(), queue_name);
+ log->Printf ("SBBreakpoint(%p)::SetQueueName (%s)",
+ static_cast<void*>(m_opaque_sp.get()), queue_name);
if (m_opaque_sp)
{
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
@@ -472,7 +493,8 @@ SBBreakpoint::GetQueueName () const
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::GetQueueName () => %s", m_opaque_sp.get(), name);
+ log->Printf ("SBBreakpoint(%p)::GetQueueName () => %s",
+ static_cast<void*>(m_opaque_sp.get()), name);
return name;
}
@@ -488,7 +510,9 @@ SBBreakpoint::GetNumResolvedLocations() const
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::GetNumResolvedLocations () => %" PRIu64, m_opaque_sp.get(), (uint64_t)num_resolved);
+ log->Printf ("SBBreakpoint(%p)::GetNumResolvedLocations () => %" PRIu64,
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<uint64_t>(num_resolved));
return num_resolved;
}
@@ -503,7 +527,9 @@ SBBreakpoint::GetNumLocations() const
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBreakpoint(%p)::GetNumLocations () => %" PRIu64, m_opaque_sp.get(), (uint64_t)num_locs);
+ log->Printf ("SBBreakpoint(%p)::GetNumLocations () => %" PRIu64,
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<uint64_t>(num_locs));
return num_locs;
}
@@ -567,9 +593,14 @@ void
SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
if (log)
- log->Printf ("SBBreakpoint(%p)::SetCallback (callback=%p, baton=%p)", m_opaque_sp.get(), callback, baton);
+ {
+ void *pointer = &callback;
+ log->Printf ("SBBreakpoint(%p)::SetCallback (callback=%p, baton=%p)",
+ static_cast<void*>(m_opaque_sp.get()),
+ *static_cast<void**>(&pointer), static_cast<void*>(baton));
+ }
if (m_opaque_sp)
{
@@ -579,6 +610,48 @@ SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton)
}
}
+void
+SBBreakpoint::SetScriptCallbackFunction (const char *callback_function_name)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+ if (log)
+ log->Printf ("SBBreakpoint(%p)::SetScriptCallbackFunction (callback=%s)",
+ static_cast<void*>(m_opaque_sp.get()),
+ callback_function_name);
+
+ if (m_opaque_sp)
+ {
+ Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
+ BreakpointOptions *bp_options = m_opaque_sp->GetOptions();
+ m_opaque_sp->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter()->SetBreakpointCommandCallbackFunction (bp_options,
+ callback_function_name);
+ }
+}
+
+SBError
+SBBreakpoint::SetScriptCallbackBody (const char *callback_body_text)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+ if (log)
+ log->Printf ("SBBreakpoint(%p)::SetScriptCallbackBody: callback body:\n%s)",
+ static_cast<void*>(m_opaque_sp.get()), callback_body_text);
+
+ SBError sb_error;
+ if (m_opaque_sp)
+ {
+ Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
+ BreakpointOptions *bp_options = m_opaque_sp->GetOptions();
+ Error error = m_opaque_sp->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
+ callback_body_text);
+ sb_error.SetError(error);
+ }
+ else
+ sb_error.SetErrorString("invalid breakpoint");
+
+ return sb_error;
+}
lldb_private::Breakpoint *
SBBreakpoint::operator->() const
diff --git a/source/API/SBBreakpointLocation.cpp b/source/API/SBBreakpointLocation.cpp
index 6fdf59f38b4a..4390e9ad737a 100644
--- a/source/API/SBBreakpointLocation.cpp
+++ b/source/API/SBBreakpointLocation.cpp
@@ -17,10 +17,13 @@
#include "lldb/lldb-defines.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Target/ThreadSpec.h"
+#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Target/ThreadSpec.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
@@ -43,7 +46,9 @@ SBBreakpointLocation::SBBreakpointLocation (const lldb::BreakpointLocationSP &br
SBStream sstr;
GetDescription (sstr, lldb::eDescriptionLevelBrief);
log->Printf ("SBBreakpointLocation::SBBreakpointLocaiton (const lldb::BreakpointLocationsSP &break_loc_sp"
- "=%p) => this.sp = %p (%s)", break_loc_sp.get(), m_opaque_sp.get(), sstr.GetData());
+ "=%p) => this.sp = %p (%s)",
+ static_cast<void*>(break_loc_sp.get()),
+ static_cast<void*>(m_opaque_sp.get()), sstr.GetData());
}
}
@@ -160,6 +165,49 @@ SBBreakpointLocation::GetCondition ()
}
void
+SBBreakpointLocation::SetScriptCallbackFunction (const char *callback_function_name)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+ if (log)
+ log->Printf ("SBBreakpointLocation(%p)::SetScriptCallbackFunction (callback=%s)",
+ static_cast<void*>(m_opaque_sp.get()),
+ callback_function_name);
+
+ if (m_opaque_sp)
+ {
+ Mutex::Locker api_locker (m_opaque_sp->GetBreakpoint().GetTarget().GetAPIMutex());
+ BreakpointOptions *bp_options = m_opaque_sp->GetLocationOptions();
+ m_opaque_sp->GetBreakpoint().GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter()->SetBreakpointCommandCallbackFunction (bp_options,
+ callback_function_name);
+ }
+}
+
+SBError
+SBBreakpointLocation::SetScriptCallbackBody (const char *callback_body_text)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+ if (log)
+ log->Printf ("SBBreakpoint(%p)::SetScriptCallbackBody: callback body:\n%s)",
+ static_cast<void*>(m_opaque_sp.get()), callback_body_text);
+
+ SBError sb_error;
+ if (m_opaque_sp)
+ {
+ Mutex::Locker api_locker (m_opaque_sp->GetBreakpoint().GetTarget().GetAPIMutex());
+ BreakpointOptions *bp_options = m_opaque_sp->GetLocationOptions();
+ Error error = m_opaque_sp->GetBreakpoint().GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
+ callback_body_text);
+ sb_error.SetError(error);
+ }
+ else
+ sb_error.SetErrorString("invalid breakpoint");
+
+ return sb_error;
+}
+
+void
SBBreakpointLocation::SetThreadID (tid_t thread_id)
{
if (m_opaque_sp)
@@ -312,8 +360,9 @@ SBBreakpointLocation::GetBreakpoint ()
{
SBStream sstr;
sb_bp.GetDescription (sstr);
- log->Printf ("SBBreakpointLocation(%p)::GetBreakpoint () => SBBreakpoint(%p) %s",
- m_opaque_sp.get(), sb_bp.get(), sstr.GetData());
+ log->Printf ("SBBreakpointLocation(%p)::GetBreakpoint () => SBBreakpoint(%p) %s",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(sb_bp.get()), sstr.GetData());
}
return sb_bp;
}
diff --git a/source/API/SBBroadcaster.cpp b/source/API/SBBroadcaster.cpp
index 7168305ac80b..73eac5183f8a 100644
--- a/source/API/SBBroadcaster.cpp
+++ b/source/API/SBBroadcaster.cpp
@@ -33,7 +33,7 @@ SBBroadcaster::SBBroadcaster (const char *name) :
if (log)
log->Printf ("SBBroadcaster::SBBroadcaster (name=\"%s\") => SBBroadcaster(%p)",
- name, m_opaque_ptr);
+ name, static_cast<void*>(m_opaque_ptr));
}
SBBroadcaster::SBBroadcaster (lldb_private::Broadcaster *broadcaster, bool owns) :
@@ -43,8 +43,9 @@ SBBroadcaster::SBBroadcaster (lldb_private::Broadcaster *broadcaster, bool owns)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API | LIBLLDB_LOG_VERBOSE));
if (log)
- log->Printf ("SBBroadcaster::SBBroadcaster (broadcaster=%p, bool owns=%i) => SBBroadcaster(%p)",
- broadcaster, owns, m_opaque_ptr);
+ log->Printf ("SBBroadcaster::SBBroadcaster (broadcaster=%p, bool owns=%i) => SBBroadcaster(%p)",
+ static_cast<void*>(broadcaster), owns,
+ static_cast<void*>(m_opaque_ptr));
}
SBBroadcaster::SBBroadcaster (const SBBroadcaster &rhs) :
@@ -75,7 +76,8 @@ SBBroadcaster::BroadcastEventByType (uint32_t event_type, bool unique)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBroadcaster(%p)::BroadcastEventByType (event_type=0x%8.8x, unique=%i)", m_opaque_ptr, event_type, unique);
+ log->Printf ("SBBroadcaster(%p)::BroadcastEventByType (event_type=0x%8.8x, unique=%i)",
+ static_cast<void*>(m_opaque_ptr), event_type, unique);
if (m_opaque_ptr == NULL)
return;
@@ -92,7 +94,9 @@ SBBroadcaster::BroadcastEvent (const SBEvent &event, bool unique)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBroadcaster(%p)::BroadcastEventByType (SBEvent(%p), unique=%i)", m_opaque_ptr, event.get(), unique);
+ log->Printf ("SBBroadcaster(%p)::BroadcastEventByType (SBEvent(%p), unique=%i)",
+ static_cast<void*>(m_opaque_ptr),
+ static_cast<void*>(event.get()), unique);
if (m_opaque_ptr == NULL)
return;
@@ -109,7 +113,9 @@ SBBroadcaster::AddInitialEventsToListener (const SBListener &listener, uint32_t
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBBroadcaster(%p)::AddInitialEventsToListener (SBListener(%p), event_mask=0x%8.8x)", m_opaque_ptr, listener.get(), requested_events);
+ log->Printf ("SBBroadcaster(%p)::AddInitialEventsToListener (SBListener(%p), event_mask=0x%8.8x)",
+ static_cast<void*>(m_opaque_ptr),
+ static_cast<void*>(listener.get()), requested_events);
if (m_opaque_ptr)
m_opaque_ptr->AddInitialEventsToListener (listener.get(), requested_events);
}
diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp
index f1faa13ba981..e1adea795b08 100644
--- a/source/API/SBCommandInterpreter.cpp
+++ b/source/API/SBCommandInterpreter.cpp
@@ -65,7 +65,9 @@ SBCommandInterpreter::SBCommandInterpreter (CommandInterpreter *interpreter) :
if (log)
log->Printf ("SBCommandInterpreter::SBCommandInterpreter (interpreter=%p)"
- " => SBCommandInterpreter(%p)", interpreter, m_opaque_ptr);
+ " => SBCommandInterpreter(%p)",
+ static_cast<void*>(interpreter),
+ static_cast<void*>(m_opaque_ptr));
}
SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs) :
@@ -129,12 +131,14 @@ SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnOb
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", SBCommandReturnObject(%p), add_to_history=%i)",
- m_opaque_ptr, command_line, result.get(), add_to_history);
+ log->Printf ("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", SBCommandReturnObject(%p), add_to_history=%i)",
+ static_cast<void*>(m_opaque_ptr), command_line,
+ static_cast<void*>(result.get()), add_to_history);
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());
}
else
@@ -150,7 +154,9 @@ SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnOb
SBStream sstr;
result.GetDescription (sstr);
log->Printf ("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", SBCommandReturnObject(%p): %s, add_to_history=%i) => %i",
- m_opaque_ptr, command_line, result.get(), sstr.GetData(), add_to_history, result.GetStatus());
+ static_cast<void*>(m_opaque_ptr), command_line,
+ static_cast<void*>(result.get()), sstr.GetData(),
+ add_to_history, result.GetStatus());
}
return result.GetStatus();
@@ -166,23 +172,27 @@ SBCommandInterpreter::HandleCompletion (const char *current_line,
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
int num_completions = 0;
-
+
// Sanity check the arguments that are passed in:
// cursor & last_char have to be within the current_line.
if (current_line == NULL || cursor == NULL || last_char == NULL)
return 0;
-
+
if (cursor < current_line || last_char < current_line)
return 0;
-
+
size_t current_line_size = strlen (current_line);
- if (cursor - current_line > current_line_size || last_char - current_line > current_line_size)
+ if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) ||
+ last_char - current_line > static_cast<ptrdiff_t>(current_line_size))
return 0;
-
+
if (log)
log->Printf ("SBCommandInterpreter(%p)::HandleCompletion (current_line=\"%s\", cursor at: %" PRId64 ", last char at: %" PRId64 ", match_start_point: %d, max_return_elements: %d)",
- m_opaque_ptr, current_line, (uint64_t) (cursor - current_line), (uint64_t) (last_char - current_line), match_start_point, max_return_elements);
-
+ static_cast<void*>(m_opaque_ptr), current_line,
+ static_cast<uint64_t>(cursor - current_line),
+ static_cast<uint64_t>(last_char - current_line),
+ match_start_point, max_return_elements);
+
if (m_opaque_ptr)
{
lldb_private::StringList lldb_matches;
@@ -193,8 +203,9 @@ SBCommandInterpreter::HandleCompletion (const char *current_line,
matches.AppendList (temp_list);
}
if (log)
- log->Printf ("SBCommandInterpreter(%p)::HandleCompletion - Found %d completions.", m_opaque_ptr, num_completions);
-
+ log->Printf ("SBCommandInterpreter(%p)::HandleCompletion - Found %d completions.",
+ static_cast<void*>(m_opaque_ptr), num_completions);
+
return num_completions;
}
@@ -253,9 +264,9 @@ SBCommandInterpreter::GetProcess ()
if (log)
log->Printf ("SBCommandInterpreter(%p)::GetProcess () => SBProcess(%p)",
- m_opaque_ptr, process_sp.get());
+ static_cast<void*>(m_opaque_ptr),
+ static_cast<void*>(process_sp.get()));
-
return sb_process;
}
@@ -266,12 +277,12 @@ SBCommandInterpreter::GetDebugger ()
if (m_opaque_ptr)
sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this());
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
if (log)
log->Printf ("SBCommandInterpreter(%p)::GetDebugger () => SBDebugger(%p)",
- m_opaque_ptr, sb_debugger.get());
-
-
+ static_cast<void*>(m_opaque_ptr),
+ static_cast<void*>(sb_debugger.get()));
+
return sb_debugger;
}
@@ -315,8 +326,8 @@ SBCommandInterpreter::SourceInitFileInHomeDirectory (SBCommandReturnObject &resu
if (log)
log->Printf ("SBCommandInterpreter(%p)::SourceInitFileInHomeDirectory (&SBCommandReturnObject(%p))",
- m_opaque_ptr, result.get());
-
+ static_cast<void*>(m_opaque_ptr),
+ static_cast<void*>(result.get()));
}
void
@@ -340,7 +351,8 @@ SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory (SBCommandReturnOb
if (log)
log->Printf ("SBCommandInterpreter(%p)::SourceInitFileInCurrentWorkingDirectory (&SBCommandReturnObject(%p))",
- m_opaque_ptr, result.get());
+ static_cast<void*>(m_opaque_ptr),
+ static_cast<void*>(result.get()));
}
SBBroadcaster
@@ -352,7 +364,7 @@ SBCommandInterpreter::GetBroadcaster ()
if (log)
log->Printf ("SBCommandInterpreter(%p)::GetBroadcaster() => SBBroadcaster(%p)",
- m_opaque_ptr, broadcaster.get());
+ static_cast<void*>(m_opaque_ptr), static_cast<void*>(broadcaster.get()));
return broadcaster;
}
diff --git a/source/API/SBCommandReturnObject.cpp b/source/API/SBCommandReturnObject.cpp
index 83d65637d3f2..1ae2df76c979 100644
--- a/source/API/SBCommandReturnObject.cpp
+++ b/source/API/SBCommandReturnObject.cpp
@@ -75,14 +75,16 @@ SBCommandReturnObject::GetOutput ()
if (m_opaque_ap.get())
{
if (log)
- log->Printf ("SBCommandReturnObject(%p)::GetOutput () => \"%s\"", m_opaque_ap.get(),
+ log->Printf ("SBCommandReturnObject(%p)::GetOutput () => \"%s\"",
+ static_cast<void*>(m_opaque_ap.get()),
m_opaque_ap->GetOutputData());
return m_opaque_ap->GetOutputData();
}
if (log)
- log->Printf ("SBCommandReturnObject(%p)::GetOutput () => NULL", m_opaque_ap.get());
+ log->Printf ("SBCommandReturnObject(%p)::GetOutput () => NULL",
+ static_cast<void*>(m_opaque_ap.get()));
return NULL;
}
@@ -95,14 +97,16 @@ SBCommandReturnObject::GetError ()
if (m_opaque_ap.get())
{
if (log)
- log->Printf ("SBCommandReturnObject(%p)::GetError () => \"%s\"", m_opaque_ap.get(),
+ log->Printf ("SBCommandReturnObject(%p)::GetError () => \"%s\"",
+ static_cast<void*>(m_opaque_ap.get()),
m_opaque_ap->GetErrorData());
return m_opaque_ap->GetErrorData();
}
-
+
if (log)
- log->Printf ("SBCommandReturnObject(%p)::GetError () => NULL", m_opaque_ap.get());
+ log->Printf ("SBCommandReturnObject(%p)::GetError () => NULL",
+ static_cast<void*>(m_opaque_ap.get()));
return NULL;
}
diff --git a/source/API/SBCommunication.cpp b/source/API/SBCommunication.cpp
index 10feae5d4ebb..df0b864fad94 100644
--- a/source/API/SBCommunication.cpp
+++ b/source/API/SBCommunication.cpp
@@ -32,7 +32,8 @@ SBCommunication::SBCommunication(const char * broadcaster_name) :
if (log)
log->Printf ("SBCommunication::SBCommunication (broadcaster_name=\"%s\") => "
- "SBCommunication(%p)", broadcaster_name, m_opaque);
+ "SBCommunication(%p)", broadcaster_name,
+ static_cast<void*>(m_opaque));
}
SBCommunication::~SBCommunication()
@@ -97,8 +98,9 @@ SBCommunication::AdoptFileDesriptor (int fd, bool owns_fd)
}
if (log)
- log->Printf ("SBCommunication(%p)::AdoptFileDescriptor (fd=%d, ownd_fd=%i) => %s",
- m_opaque, fd, owns_fd, Communication::ConnectionStatusAsCString (status));
+ log->Printf ("SBCommunication(%p)::AdoptFileDescriptor (fd=%d, ownd_fd=%i) => %s",
+ static_cast<void*>(m_opaque), fd, owns_fd,
+ Communication::ConnectionStatusAsCString (status));
return status;
}
@@ -114,7 +116,8 @@ SBCommunication::Disconnect ()
status = m_opaque->Disconnect ();
if (log)
- log->Printf ("SBCommunication(%p)::Disconnect () => %s", m_opaque,
+ log->Printf ("SBCommunication(%p)::Disconnect () => %s",
+ static_cast<void*>(m_opaque),
Communication::ConnectionStatusAsCString (status));
return status;
@@ -129,7 +132,8 @@ SBCommunication::IsConnected () const
result = m_opaque->IsConnected ();
if (log)
- log->Printf ("SBCommunication(%p)::IsConnected () => %i", m_opaque, result);
+ log->Printf ("SBCommunication(%p)::IsConnected () => %i",
+ static_cast<void*>(m_opaque), result);
return false;
}
@@ -140,10 +144,8 @@ SBCommunication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, Connect
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
log->Printf ("SBCommunication(%p)::Read (dst=%p, dst_len=%" PRIu64 ", timeout_usec=%u, &status)...",
- m_opaque,
- dst,
- (uint64_t)dst_len,
- timeout_usec);
+ static_cast<void*>(m_opaque), static_cast<void*>(dst),
+ static_cast<uint64_t>(dst_len), timeout_usec);
size_t bytes_read = 0;
if (m_opaque)
bytes_read = m_opaque->Read (dst, dst_len, timeout_usec, status, NULL);
@@ -152,12 +154,10 @@ SBCommunication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, Connect
if (log)
log->Printf ("SBCommunication(%p)::Read (dst=%p, dst_len=%" PRIu64 ", timeout_usec=%u, &status=%s) => %" PRIu64,
- m_opaque,
- dst,
- (uint64_t)dst_len,
- timeout_usec,
+ static_cast<void*>(m_opaque), static_cast<void*>(dst),
+ static_cast<uint64_t>(dst_len), timeout_usec,
Communication::ConnectionStatusAsCString (status),
- (uint64_t)bytes_read);
+ static_cast<uint64_t>(bytes_read));
return bytes_read;
}
@@ -174,7 +174,10 @@ SBCommunication::Write (const void *src, size_t src_len, ConnectionStatus &statu
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
log->Printf ("SBCommunication(%p)::Write (src=%p, src_len=%" PRIu64 ", &status=%s) => %" PRIu64,
- m_opaque, src, (uint64_t)src_len, Communication::ConnectionStatusAsCString (status), (uint64_t)bytes_written);
+ static_cast<void*>(m_opaque), static_cast<const void*>(src),
+ static_cast<uint64_t>(src_len),
+ Communication::ConnectionStatusAsCString (status),
+ static_cast<uint64_t>(bytes_written));
return 0;
}
@@ -189,7 +192,8 @@ SBCommunication::ReadThreadStart ()
success = m_opaque->StartReadThread ();
if (log)
- log->Printf ("SBCommunication(%p)::ReadThreadStart () => %i", m_opaque, success);
+ log->Printf ("SBCommunication(%p)::ReadThreadStart () => %i",
+ static_cast<void*>(m_opaque), success);
return success;
}
@@ -200,14 +204,16 @@ SBCommunication::ReadThreadStop ()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBCommunication(%p)::ReadThreadStop ()...", m_opaque);
+ log->Printf ("SBCommunication(%p)::ReadThreadStop ()...",
+ static_cast<void*>(m_opaque));
bool success = false;
if (m_opaque)
success = m_opaque->StopReadThread ();
if (log)
- log->Printf ("SBCommunication(%p)::ReadThreadStop () => %i", m_opaque, success);
+ log->Printf ("SBCommunication(%p)::ReadThreadStop () => %i",
+ static_cast<void*>(m_opaque), success);
return success;
}
@@ -220,7 +226,8 @@ SBCommunication::ReadThreadIsRunning ()
result = m_opaque->ReadThreadIsRunning ();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBCommunication(%p)::ReadThreadIsRunning () => %i", m_opaque, result);
+ log->Printf ("SBCommunication(%p)::ReadThreadIsRunning () => %i",
+ static_cast<void*>(m_opaque), result);
return result;
}
@@ -242,7 +249,9 @@ SBCommunication::SetReadThreadBytesReceivedCallback
if (log)
log->Printf ("SBCommunication(%p)::SetReadThreadBytesReceivedCallback (callback=%p, baton=%p) => %i",
- m_opaque, callback, callback_baton, result);
+ static_cast<void*>(m_opaque),
+ reinterpret_cast<void*>(reinterpret_cast<intptr_t>(callback)),
+ static_cast<void*>(callback_baton), result);
return result;
}
@@ -256,7 +265,8 @@ SBCommunication::GetBroadcaster ()
if (log)
log->Printf ("SBCommunication(%p)::GetBroadcaster () => SBBroadcaster (%p)",
- m_opaque, broadcaster.get());
+ static_cast<void*>(m_opaque),
+ static_cast<void*>(broadcaster.get()));
return broadcaster;
}
diff --git a/source/API/SBCompileUnit.cpp b/source/API/SBCompileUnit.cpp
index 9f7487746a85..03c25710a9e4 100644
--- a/source/API/SBCompileUnit.cpp
+++ b/source/API/SBCompileUnit.cpp
@@ -87,13 +87,14 @@ SBCompileUnit::GetLineEntryAtIndex (uint32_t idx) const
sb_line_entry.SetLineEntry(line_entry);
}
}
-
+
if (log)
{
SBStream sstr;
sb_line_entry.GetDescription (sstr);
- log->Printf ("SBCompileUnit(%p)::GetLineEntryAtIndex (idx=%u) => SBLineEntry(%p): '%s'",
- m_opaque_ptr, idx, sb_line_entry.get(), sstr.GetData());
+ log->Printf ("SBCompileUnit(%p)::GetLineEntryAtIndex (idx=%u) => SBLineEntry(%p): '%s'",
+ static_cast<void*>(m_opaque_ptr), idx,
+ static_cast<void*>(sb_line_entry.get()), sstr.GetData());
}
return sb_line_entry;
@@ -120,7 +121,6 @@ SBCompileUnit::FindLineEntryIndex (uint32_t start_idx, uint32_t line, SBFileSpec
else
file_spec = *m_opaque_ptr;
-
index = m_opaque_ptr->FindLineEntry (start_idx,
line,
inline_file_spec ? inline_file_spec->get() : NULL,
@@ -133,13 +133,20 @@ SBCompileUnit::FindLineEntryIndex (uint32_t start_idx, uint32_t line, SBFileSpec
SBStream sstr;
if (index == UINT32_MAX)
{
- log->Printf ("SBCompileUnit(%p)::FindLineEntryIndex (start_idx=%u, line=%u, SBFileSpec(%p)) => NOT FOUND",
- m_opaque_ptr, start_idx, line, inline_file_spec ? inline_file_spec->get() : NULL);
+ log->Printf ("SBCompileUnit(%p)::FindLineEntryIndex (start_idx=%u, line=%u, SBFileSpec(%p)) => NOT FOUND",
+ static_cast<void*>(m_opaque_ptr), start_idx, line,
+ inline_file_spec
+ ? static_cast<const void*>(inline_file_spec->get())
+ : NULL);
}
else
{
- log->Printf ("SBCompileUnit(%p)::FindLineEntryIndex (start_idx=%u, line=%u, SBFileSpec(%p)) => %u",
- m_opaque_ptr, start_idx, line, inline_file_spec ? inline_file_spec->get() : NULL, index);
+ log->Printf ("SBCompileUnit(%p)::FindLineEntryIndex (start_idx=%u, line=%u, SBFileSpec(%p)) => %u",
+ static_cast<void*>(m_opaque_ptr), start_idx, line,
+ inline_file_spec
+ ? static_cast<const void*>(inline_file_spec->get())
+ : NULL,
+ index);
}
}
@@ -196,13 +203,15 @@ SBCompileUnit::GetSupportFileAtIndex (uint32_t idx) const
FileSpec file_spec = support_files.GetFileSpecAtIndex(idx);
sb_file_spec.SetFileSpec(file_spec);
}
-
+
if (log)
{
SBStream sstr;
sb_file_spec.GetDescription (sstr);
- log->Printf ("SBCompileUnit(%p)::GetGetFileSpecAtIndex (idx=%u) => SBFileSpec(%p): '%s'",
- m_opaque_ptr, idx, sb_file_spec.get(), sstr.GetData());
+ log->Printf ("SBCompileUnit(%p)::GetGetFileSpecAtIndex (idx=%u) => SBFileSpec(%p): '%s'",
+ static_cast<void*>(m_opaque_ptr), idx,
+ static_cast<const void*>(sb_file_spec.get()),
+ sstr.GetData());
}
return sb_file_spec;
diff --git a/source/API/SBData.cpp b/source/API/SBData.cpp
index 06dcfc12af41..a58585295a21 100644
--- a/source/API/SBData.cpp
+++ b/source/API/SBData.cpp
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include <inttypes.h> // PRIu64
+
#include "lldb/API/SBData.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBStream.h"
@@ -122,7 +124,7 @@ SBData::GetByteSize ()
value = m_opaque_sp->GetByteSize();
if (log)
log->Printf ("SBData::GetByteSize () => "
- "(%zu)", value);
+ "( %" PRIu64 " )", (uint64_t)value);
return value;
}
@@ -167,8 +169,8 @@ SBData::GetFloat (lldb::SBError& error, lldb::offset_t offset)
error.SetErrorString("unable to read data");
}
if (log)
- log->Printf ("SBData::GetFloat (error=%p,offset=%" PRIu64 ") => "
- "(%f)", error.get(), offset, value);
+ log->Printf ("SBData::GetFloat (error=%p,offset=%" PRIu64 ") => (%f)",
+ static_cast<void*>(error.get()), offset, value);
return value;
}
@@ -190,7 +192,7 @@ SBData::GetDouble (lldb::SBError& error, lldb::offset_t offset)
}
if (log)
log->Printf ("SBData::GetDouble (error=%p,offset=%" PRIu64 ") => "
- "(%f)", error.get(), offset, value);
+ "(%f)", static_cast<void*>(error.get()), offset, value);
return value;
}
@@ -212,7 +214,7 @@ SBData::GetLongDouble (lldb::SBError& error, lldb::offset_t offset)
}
if (log)
log->Printf ("SBData::GetLongDouble (error=%p,offset=%" PRIu64 ") => "
- "(%Lf)", error.get(), offset, value);
+ "(%Lf)", static_cast<void*>(error.get()), offset, value);
return value;
}
@@ -234,7 +236,8 @@ SBData::GetAddress (lldb::SBError& error, lldb::offset_t offset)
}
if (log)
log->Printf ("SBData::GetAddress (error=%p,offset=%" PRIu64 ") => "
- "(%p)", error.get(), offset, (void*)value);
+ "(%p)", static_cast<void*>(error.get()), offset,
+ reinterpret_cast<void*>(value));
return value;
}
@@ -256,7 +259,7 @@ SBData::GetUnsignedInt8 (lldb::SBError& error, lldb::offset_t offset)
}
if (log)
log->Printf ("SBData::GetUnsignedInt8 (error=%p,offset=%" PRIu64 ") => "
- "(%c)", error.get(), offset, value);
+ "(%c)", static_cast<void*>(error.get()), offset, value);
return value;
}
@@ -278,7 +281,7 @@ SBData::GetUnsignedInt16 (lldb::SBError& error, lldb::offset_t offset)
}
if (log)
log->Printf ("SBData::GetUnsignedInt16 (error=%p,offset=%" PRIu64 ") => "
- "(%hd)", error.get(), offset, value);
+ "(%hd)", static_cast<void*>(error.get()), offset, value);
return value;
}
@@ -300,7 +303,7 @@ SBData::GetUnsignedInt32 (lldb::SBError& error, lldb::offset_t offset)
}
if (log)
log->Printf ("SBData::GetUnsignedInt32 (error=%p,offset=%" PRIu64 ") => "
- "(%d)", error.get(), offset, value);
+ "(%d)", static_cast<void*>(error.get()), offset, value);
return value;
}
@@ -322,7 +325,8 @@ SBData::GetUnsignedInt64 (lldb::SBError& error, lldb::offset_t offset)
}
if (log)
log->Printf ("SBData::GetUnsignedInt64 (error=%p,offset=%" PRIu64 ") => "
- "(%" PRId64 ")", error.get(), offset, value);
+ "(%" PRId64 ")", static_cast<void*>(error.get()), offset,
+ value);
return value;
}
@@ -344,7 +348,7 @@ SBData::GetSignedInt8 (lldb::SBError& error, lldb::offset_t offset)
}
if (log)
log->Printf ("SBData::GetSignedInt8 (error=%p,offset=%" PRIu64 ") => "
- "(%c)", error.get(), offset, value);
+ "(%c)", static_cast<void*>(error.get()), offset, value);
return value;
}
@@ -366,7 +370,7 @@ SBData::GetSignedInt16 (lldb::SBError& error, lldb::offset_t offset)
}
if (log)
log->Printf ("SBData::GetSignedInt16 (error=%p,offset=%" PRIu64 ") => "
- "(%hd)", error.get(), offset, value);
+ "(%hd)", static_cast<void*>(error.get()), offset, value);
return value;
}
@@ -388,7 +392,7 @@ SBData::GetSignedInt32 (lldb::SBError& error, lldb::offset_t offset)
}
if (log)
log->Printf ("SBData::GetSignedInt32 (error=%p,offset=%" PRIu64 ") => "
- "(%d)", error.get(), offset, value);
+ "(%d)", static_cast<void*>(error.get()), offset, value);
return value;
}
@@ -410,7 +414,8 @@ SBData::GetSignedInt64 (lldb::SBError& error, lldb::offset_t offset)
}
if (log)
log->Printf ("SBData::GetSignedInt64 (error=%p,offset=%" PRIu64 ") => "
- "(%" PRId64 ")", error.get(), offset, value);
+ "(%" PRId64 ")", static_cast<void*>(error.get()), offset,
+ value);
return value;
}
@@ -431,8 +436,9 @@ SBData::GetString (lldb::SBError& error, lldb::offset_t offset)
error.SetErrorString("unable to read data");
}
if (log)
- log->Printf ("SBData::GetString (error=%p,offset=%" PRIu64 ") => "
- "(%p)", error.get(), offset, value);
+ log->Printf ("SBData::GetString (error=%p,offset=%" PRIu64 ") => (%p)",
+ static_cast<void*>(error.get()), offset,
+ static_cast<const void*>(value));
return value;
}
@@ -479,8 +485,10 @@ SBData::ReadRawData (lldb::SBError& error,
error.SetErrorString("unable to read data");
}
if (log)
- log->Printf ("SBData::ReadRawData (error=%p,offset=%" PRIu64 ",buf=%p,size=%zu) => "
- "(%p)", error.get(), offset, buf, size, ok);
+ log->Printf("SBData::ReadRawData (error=%p,offset=%" PRIu64 ",buf=%p,size=%" PRIu64 ") => "
+ "(%p)", static_cast<void*>(error.get()), offset,
+ static_cast<void*>(buf), static_cast<uint64_t>(size),
+ static_cast<void*>(ok));
return ok ? size : 0;
}
@@ -497,8 +505,10 @@ SBData::SetData (lldb::SBError& error,
else
m_opaque_sp->SetData(buf, size, endian);
if (log)
- log->Printf ("SBData::SetData (error=%p,buf=%p,size=%zu,endian=%d,addr_size=%c) => "
- "(%p)", error.get(), buf, size, endian, addr_size, m_opaque_sp.get());
+ log->Printf("SBData::SetData (error=%p,buf=%p,size=%" PRIu64 ",endian=%d,addr_size=%c) => "
+ "(%p)", static_cast<void*>(error.get()),
+ static_cast<const void*>(buf), static_cast<uint64_t>(size),
+ endian, addr_size, static_cast<void*>(m_opaque_sp.get()));
}
bool
@@ -509,8 +519,8 @@ SBData::Append (const SBData& rhs)
if (m_opaque_sp.get() && rhs.m_opaque_sp.get())
value = m_opaque_sp.get()->Append(*rhs.m_opaque_sp);
if (log)
- log->Printf ("SBData::Append (rhs=%p) => "
- "(%s)", rhs.get(), value ? "true" : "false");
+ log->Printf ("SBData::Append (rhs=%p) => (%s)",
+ static_cast<void*>(rhs.get()), value ? "true" : "false");
return value;
}
@@ -614,28 +624,28 @@ bool
SBData::SetDataFromCString (const char* data)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
if (!data)
{
if (log)
- log->Printf ("SBData::SetDataFromCString (data=%p) => "
- "false", data);
+ log->Printf ("SBData::SetDataFromCString (data=%p) => false",
+ static_cast<const void*>(data));
return false;
}
-
+
size_t data_len = strlen(data);
-
+
lldb::DataBufferSP buffer_sp(new DataBufferHeap(data, data_len));
-
+
if (!m_opaque_sp.get())
m_opaque_sp.reset(new DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()));
else
m_opaque_sp->SetData(buffer_sp);
-
+
if (log)
- log->Printf ("SBData::SetDataFromCString (data=%p) => "
- "true", data);
-
+ log->Printf ("SBData::SetDataFromCString (data=%p) => true",
+ static_cast<const void*>(data));
+
return true;
}
@@ -643,28 +653,30 @@ bool
SBData::SetDataFromUInt64Array (uint64_t* array, size_t array_len)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
if (!array || array_len == 0)
{
if (log)
- log->Printf ("SBData::SetDataFromUInt64Array (array=%p, array_len = %zu) => "
- "false", array, array_len);
+ log->Printf("SBData::SetDataFromUInt64Array (array=%p, array_len = %" PRIu64 ") => "
+ "false", static_cast<void*>(array),
+ static_cast<uint64_t>(array_len));
return false;
}
size_t data_len = array_len * sizeof(uint64_t);
-
+
lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
-
+
if (!m_opaque_sp.get())
m_opaque_sp.reset(new DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()));
else
m_opaque_sp->SetData(buffer_sp);
-
+
if (log)
- log->Printf ("SBData::SetDataFromUInt64Array (array=%p, array_len = %zu) => "
- "true", array, array_len);
-
+ log->Printf("SBData::SetDataFromUInt64Array (array=%p, array_len = %" PRIu64 ") => "
+ "true", static_cast<void*>(array),
+ static_cast<uint64_t>(array_len));
+
return true;
}
@@ -672,28 +684,30 @@ bool
SBData::SetDataFromUInt32Array (uint32_t* array, size_t array_len)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
if (!array || array_len == 0)
{
if (log)
- log->Printf ("SBData::SetDataFromUInt32Array (array=%p, array_len = %zu) => "
- "false", array, array_len);
+ log->Printf("SBData::SetDataFromUInt32Array (array=%p, array_len = %" PRIu64 ") => "
+ "false", static_cast<void*>(array),
+ static_cast<uint64_t>(array_len));
return false;
}
-
+
size_t data_len = array_len * sizeof(uint32_t);
-
+
lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
-
+
if (!m_opaque_sp.get())
m_opaque_sp.reset(new DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()));
else
m_opaque_sp->SetData(buffer_sp);
-
+
if (log)
- log->Printf ("SBData::SetDataFromUInt32Array (array=%p, array_len = %zu) => "
- "true", array, array_len);
-
+ log->Printf("SBData::SetDataFromUInt32Array (array=%p, array_len = %" PRIu64 ") => "
+ "true", static_cast<void*>(array),
+ static_cast<uint64_t>(array_len));
+
return true;
}
@@ -701,28 +715,30 @@ bool
SBData::SetDataFromSInt64Array (int64_t* array, size_t array_len)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
if (!array || array_len == 0)
{
if (log)
- log->Printf ("SBData::SetDataFromSInt64Array (array=%p, array_len = %zu) => "
- "false", array, array_len);
+ log->Printf("SBData::SetDataFromSInt64Array (array=%p, array_len = %" PRIu64 ") => "
+ "false", static_cast<void*>(array),
+ static_cast<uint64_t>(array_len));
return false;
}
-
+
size_t data_len = array_len * sizeof(int64_t);
-
+
lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
-
+
if (!m_opaque_sp.get())
m_opaque_sp.reset(new DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()));
else
m_opaque_sp->SetData(buffer_sp);
-
+
if (log)
- log->Printf ("SBData::SetDataFromSInt64Array (array=%p, array_len = %zu) => "
- "true", array, array_len);
-
+ log->Printf("SBData::SetDataFromSInt64Array (array=%p, array_len = %" PRIu64 ") => "
+ "true", static_cast<void*>(array),
+ static_cast<uint64_t>(array_len));
+
return true;
}
@@ -730,28 +746,30 @@ bool
SBData::SetDataFromSInt32Array (int32_t* array, size_t array_len)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
if (!array || array_len == 0)
{
if (log)
- log->Printf ("SBData::SetDataFromSInt32Array (array=%p, array_len = %zu) => "
- "false", array, array_len);
+ log->Printf("SBData::SetDataFromSInt32Array (array=%p, array_len = %" PRIu64 ") => "
+ "false", static_cast<void*>(array),
+ static_cast<uint64_t>(array_len));
return false;
}
-
+
size_t data_len = array_len * sizeof(int32_t);
-
+
lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
-
+
if (!m_opaque_sp.get())
m_opaque_sp.reset(new DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()));
else
m_opaque_sp->SetData(buffer_sp);
-
+
if (log)
- log->Printf ("SBData::SetDataFromSInt32Array (array=%p, array_len = %zu) => "
- "true", array, array_len);
-
+ log->Printf("SBData::SetDataFromSInt32Array (array=%p, array_len = %" PRIu64 ") => "
+ "true", static_cast<void*>(array),
+ static_cast<uint64_t>(array_len));
+
return true;
}
@@ -759,27 +777,29 @@ bool
SBData::SetDataFromDoubleArray (double* array, size_t array_len)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
if (!array || array_len == 0)
{
if (log)
- log->Printf ("SBData::SetDataFromDoubleArray (array=%p, array_len = %zu) => "
- "false", array, array_len);
+ log->Printf("SBData::SetDataFromDoubleArray (array=%p, array_len = %" PRIu64 ") => "
+ "false", static_cast<void*>(array),
+ static_cast<uint64_t>(array_len));
return false;
}
-
+
size_t data_len = array_len * sizeof(double);
-
+
lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
-
+
if (!m_opaque_sp.get())
m_opaque_sp.reset(new DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()));
else
m_opaque_sp->SetData(buffer_sp);
-
+
if (log)
- log->Printf ("SBData::SetDataFromDoubleArray (array=%p, array_len = %zu) => "
- "true", array, array_len);
-
+ log->Printf("SBData::SetDataFromDoubleArray (array=%p, array_len = %" PRIu64 ") => "
+ "true", static_cast<void*>(array),
+ static_cast<uint64_t>(array_len));
+
return true;
}
diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp
index 8d6887a6c280..dae567525a4a 100644
--- a/source/API/SBDebugger.cpp
+++ b/source/API/SBDebugger.cpp
@@ -38,13 +38,14 @@
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/DataFormatters/DataVisualization.h"
-#include "lldb/Host/DynamicLibrary.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/TargetList.h"
+#include "llvm/Support/DynamicLibrary.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -72,22 +73,22 @@ SBInputReader::IsActive() const
return false;
}
-static lldb::DynamicLibrarySP
+static llvm::sys::DynamicLibrary
LoadPlugin (const lldb::DebuggerSP &debugger_sp, const FileSpec& spec, Error& error)
{
- lldb::DynamicLibrarySP dynlib_sp(new lldb_private::DynamicLibrary(spec));
- if (dynlib_sp && dynlib_sp->IsValid())
+ llvm::sys::DynamicLibrary dynlib = llvm::sys::DynamicLibrary::getPermanentLibrary(spec.GetPath().c_str());
+ if (dynlib.isValid())
{
typedef bool (*LLDBCommandPluginInit) (lldb::SBDebugger& debugger);
lldb::SBDebugger debugger_sb(debugger_sp);
// This calls the bool lldb::PluginInitialize(lldb::SBDebugger debugger) function.
// TODO: mangle this differently for your system - on OSX, the first underscore needs to be removed and the second one stays
- LLDBCommandPluginInit init_func = dynlib_sp->GetSymbol<LLDBCommandPluginInit>("_ZN4lldb16PluginInitializeENS_10SBDebuggerE");
+ LLDBCommandPluginInit init_func = (LLDBCommandPluginInit)dynlib.getAddressOfSymbol("_ZN4lldb16PluginInitializeENS_10SBDebuggerE");
if (init_func)
{
if (init_func(debugger_sb))
- return dynlib_sp;
+ return dynlib;
else
error.SetErrorString("plug-in refused to load (lldb::PluginInitialize(lldb::SBDebugger) returned false)");
}
@@ -103,7 +104,7 @@ LoadPlugin (const lldb::DebuggerSP &debugger_sp, const FileSpec& spec, Error& er
else
error.SetErrorString("no such file");
}
- return lldb::DynamicLibrarySP();
+ return llvm::sys::DynamicLibrary();
}
void
@@ -131,8 +132,9 @@ SBDebugger::Clear ()
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBDebugger(%p)::Clear ()", m_opaque_sp.get());
-
+ log->Printf ("SBDebugger(%p)::Clear ()",
+ static_cast<void*>(m_opaque_sp.get()));
+
if (m_opaque_sp)
m_opaque_sp->ClearIOHandlers ();
@@ -158,13 +160,24 @@ SBDebugger::Create(bool source_init_files, lldb::LogOutputCallback callback, voi
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBDebugger debugger;
+
+ // Currently we have issues if this function is called simultaneously on two different
+ // threads. The issues mainly revolve around the fact that the lldb_private::FormatManager
+ // uses global collections and having two threads parsing the .lldbinit files can cause
+ // mayhem. So to get around this for now we need to use a mutex to prevent bad things
+ // from happening.
+ static Mutex g_mutex(Mutex::eMutexTypeRecursive);
+ Mutex::Locker locker(g_mutex);
+
debugger.reset(Debugger::CreateInstance(callback, baton));
if (log)
{
SBStream sstr;
debugger.GetDescription (sstr);
- log->Printf ("SBDebugger::Create () => SBDebugger(%p): %s", debugger.m_opaque_sp.get(), sstr.GetData());
+ log->Printf ("SBDebugger::Create () => SBDebugger(%p): %s",
+ static_cast<void*>(debugger.m_opaque_sp.get()),
+ sstr.GetData());
}
SBCommandInterpreter interp = debugger.GetCommandInterpreter();
@@ -187,16 +200,18 @@ void
SBDebugger::Destroy (SBDebugger &debugger)
{
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
if (log)
{
SBStream sstr;
debugger.GetDescription (sstr);
- log->Printf ("SBDebugger::Destroy () => SBDebugger(%p): %s", debugger.m_opaque_sp.get(), sstr.GetData());
+ log->Printf ("SBDebugger::Destroy () => SBDebugger(%p): %s",
+ static_cast<void*>(debugger.m_opaque_sp.get()),
+ sstr.GetData());
}
-
+
Debugger::Destroy (debugger.m_opaque_sp);
-
+
if (debugger.m_opaque_sp.get() != NULL)
debugger.m_opaque_sp.reset();
}
@@ -293,8 +308,9 @@ SBDebugger::SetInputFileHandle (FILE *fh, bool transfer_ownership)
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBDebugger(%p)::SetInputFileHandle (fh=%p, transfer_ownership=%i)", m_opaque_sp.get(),
- fh, transfer_ownership);
+ log->Printf ("SBDebugger(%p)::SetInputFileHandle (fh=%p, transfer_ownership=%i)",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(fh), transfer_ownership);
if (m_opaque_sp)
m_opaque_sp->SetInputFileHandle (fh, transfer_ownership);
@@ -307,8 +323,9 @@ SBDebugger::SetOutputFileHandle (FILE *fh, bool transfer_ownership)
if (log)
- log->Printf ("SBDebugger(%p)::SetOutputFileHandle (fh=%p, transfer_ownership=%i)", m_opaque_sp.get(),
- fh, transfer_ownership);
+ log->Printf ("SBDebugger(%p)::SetOutputFileHandle (fh=%p, transfer_ownership=%i)",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(fh), transfer_ownership);
if (m_opaque_sp)
m_opaque_sp->SetOutputFileHandle (fh, transfer_ownership);
@@ -321,8 +338,9 @@ SBDebugger::SetErrorFileHandle (FILE *fh, bool transfer_ownership)
if (log)
- log->Printf ("SBDebugger(%p)::SetErrorFileHandle (fh=%p, transfer_ownership=%i)", m_opaque_sp.get(),
- fh, transfer_ownership);
+ log->Printf ("SBDebugger(%p)::SetErrorFileHandle (fh=%p, transfer_ownership=%i)",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(fh), transfer_ownership);
if (m_opaque_sp)
m_opaque_sp->SetErrorFileHandle (fh, transfer_ownership);
@@ -389,8 +407,9 @@ SBDebugger::GetCommandInterpreter ()
sb_interpreter.reset (&m_opaque_sp->GetCommandInterpreter());
if (log)
- log->Printf ("SBDebugger(%p)::GetCommandInterpreter () => SBCommandInterpreter(%p)",
- m_opaque_sp.get(), sb_interpreter.get());
+ log->Printf ("SBDebugger(%p)::GetCommandInterpreter () => SBCommandInterpreter(%p)",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(sb_interpreter.get()));
return sb_interpreter;
}
@@ -443,8 +462,9 @@ SBDebugger::GetListener ()
sb_listener.reset(&m_opaque_sp->GetListener(), false);
if (log)
- log->Printf ("SBDebugger(%p)::GetListener () => SBListener(%p)", m_opaque_sp.get(),
- sb_listener.get());
+ log->Printf ("SBDebugger(%p)::GetListener () => SBListener(%p)",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(sb_listener.get()));
return sb_listener;
}
@@ -601,14 +621,14 @@ SBDebugger::CreateTarget (const char *filename,
sb_error.Clear();
OptionGroupPlatform platform_options (false);
platform_options.SetPlatformName (platform_name);
-
+
sb_error.ref() = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp,
filename,
target_triple,
add_dependent_modules,
&platform_options,
target_sp);
-
+
if (sb_error.Success())
sb_target.SetSP (target_sp);
}
@@ -616,20 +636,14 @@ SBDebugger::CreateTarget (const char *filename,
{
sb_error.SetErrorString("invalid target");
}
-
+
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- {
- log->Printf ("SBDebugger(%p)::CreateTarget (filename=\"%s\", triple=%s, platform_name=%s, add_dependent_modules=%u, error=%s) => SBTarget(%p)",
- m_opaque_sp.get(),
- filename,
- target_triple,
- platform_name,
- add_dependent_modules,
- sb_error.GetCString(),
- target_sp.get());
- }
-
+ log->Printf ("SBDebugger(%p)::CreateTarget (filename=\"%s\", triple=%s, platform_name=%s, add_dependent_modules=%u, error=%s) => SBTarget(%p)",
+ static_cast<void*>(m_opaque_sp.get()), filename,
+ target_triple, platform_name, add_dependent_modules,
+ sb_error.GetCString(), static_cast<void*>(target_sp.get()));
+
return sb_target;
}
@@ -650,13 +664,12 @@ SBDebugger::CreateTargetWithFileAndTargetTriple (const char *filename,
target_sp));
sb_target.SetSP (target_sp);
}
-
+
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- {
- log->Printf ("SBDebugger(%p)::CreateTargetWithFileAndTargetTriple (filename=\"%s\", triple=%s) => SBTarget(%p)",
- m_opaque_sp.get(), filename, target_triple, target_sp.get());
- }
+ log->Printf ("SBDebugger(%p)::CreateTargetWithFileAndTargetTriple (filename=\"%s\", triple=%s) => SBTarget(%p)",
+ static_cast<void*>(m_opaque_sp.get()), filename,
+ target_triple, static_cast<void*>(target_sp.get()));
return sb_target;
}
@@ -688,10 +701,9 @@ SBDebugger::CreateTargetWithFileAndArch (const char *filename, const char *arch_
}
if (log)
- {
- log->Printf ("SBDebugger(%p)::CreateTargetWithFileAndArch (filename=\"%s\", arch=%s) => SBTarget(%p)",
- m_opaque_sp.get(), filename, arch_cstr, target_sp.get());
- }
+ log->Printf ("SBDebugger(%p)::CreateTargetWithFileAndArch (filename=\"%s\", arch=%s) => SBTarget(%p)",
+ static_cast<void*>(m_opaque_sp.get()), filename, arch_cstr,
+ static_cast<void*>(target_sp.get()));
return sb_target;
}
@@ -723,10 +735,9 @@ SBDebugger::CreateTarget (const char *filename)
}
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- {
- log->Printf ("SBDebugger(%p)::CreateTarget (filename=\"%s\") => SBTarget(%p)",
- m_opaque_sp.get(), filename, target_sp.get());
- }
+ log->Printf ("SBDebugger(%p)::CreateTarget (filename=\"%s\") => SBTarget(%p)",
+ static_cast<void*>(m_opaque_sp.get()), filename,
+ static_cast<void*>(target_sp.get()));
return sb_target;
}
@@ -750,9 +761,9 @@ SBDebugger::DeleteTarget (lldb::SBTarget &target)
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- {
- log->Printf ("SBDebugger(%p)::DeleteTarget (SBTarget(%p)) => %i", m_opaque_sp.get(), target.m_opaque_sp.get(), result);
- }
+ log->Printf ("SBDebugger(%p)::DeleteTarget (SBTarget(%p)) => %i",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(target.m_opaque_sp.get()), result);
return result;
}
@@ -850,8 +861,9 @@ SBDebugger::GetSelectedTarget ()
{
SBStream sstr;
sb_target.GetDescription (sstr, eDescriptionLevelBrief);
- log->Printf ("SBDebugger(%p)::GetSelectedTarget () => SBTarget(%p): %s", m_opaque_sp.get(),
- target_sp.get(), sstr.GetData());
+ log->Printf ("SBDebugger(%p)::GetSelectedTarget () => SBTarget(%p): %s",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(target_sp.get()), sstr.GetData());
}
return sb_target;
@@ -871,8 +883,9 @@ SBDebugger::SetSelectedTarget (SBTarget &sb_target)
{
SBStream sstr;
sb_target.GetDescription (sstr, eDescriptionLevelBrief);
- log->Printf ("SBDebugger(%p)::SetSelectedTarget () => SBTarget(%p): %s", m_opaque_sp.get(),
- target_sp.get(), sstr.GetData());
+ log->Printf ("SBDebugger(%p)::SetSelectedTarget () => SBTarget(%p): %s",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(target_sp.get()), sstr.GetData());
}
}
@@ -888,10 +901,10 @@ SBDebugger::GetSelectedPlatform()
sb_platform.SetSP(debugger_sp->GetPlatformList().GetSelectedPlatform());
}
if (log)
- {
- log->Printf ("SBDebugger(%p)::GetSelectedPlatform () => SBPlatform(%p): %s", m_opaque_sp.get(),
- sb_platform.GetSP().get(), sb_platform.GetName());
- }
+ log->Printf ("SBDebugger(%p)::GetSelectedPlatform () => SBPlatform(%p): %s",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(sb_platform.GetSP().get()),
+ sb_platform.GetName());
return sb_platform;
}
@@ -899,17 +912,18 @@ void
SBDebugger::SetSelectedPlatform(SBPlatform &sb_platform)
{
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
DebuggerSP debugger_sp(m_opaque_sp);
if (debugger_sp)
{
debugger_sp->GetPlatformList().SetSelectedPlatform(sb_platform.GetSP());
}
+
if (log)
- {
- log->Printf ("SBDebugger(%p)::SetSelectedPlatform (SBPlatform(%p) %s)", m_opaque_sp.get(),
- sb_platform.GetSP().get(), sb_platform.GetName());
- }
+ log->Printf ("SBDebugger(%p)::SetSelectedPlatform (SBPlatform(%p) %s)",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(sb_platform.GetSP().get()),
+ sb_platform.GetName());
}
void
@@ -1077,9 +1091,10 @@ const char *
SBDebugger::GetPrompt() const
{
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
if (log)
- log->Printf ("SBDebugger(%p)::GetPrompt () => \"%s\"", m_opaque_sp.get(),
+ log->Printf ("SBDebugger(%p)::GetPrompt () => \"%s\"",
+ static_cast<void*>(m_opaque_sp.get()),
(m_opaque_sp ? m_opaque_sp->GetPrompt() : ""));
if (m_opaque_sp)
diff --git a/source/API/SBDeclaration.cpp b/source/API/SBDeclaration.cpp
index fc90156e75ad..8aea675afeba 100644
--- a/source/API/SBDeclaration.cpp
+++ b/source/API/SBDeclaration.cpp
@@ -74,19 +74,21 @@ SBFileSpec
SBDeclaration::GetFileSpec () const
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
SBFileSpec sb_file_spec;
if (m_opaque_ap.get() && m_opaque_ap->GetFile())
sb_file_spec.SetFileSpec(m_opaque_ap->GetFile());
-
+
if (log)
{
SBStream sstr;
sb_file_spec.GetDescription (sstr);
- log->Printf ("SBLineEntry(%p)::GetFileSpec () => SBFileSpec(%p): %s", m_opaque_ap.get(),
- sb_file_spec.get(), sstr.GetData());
+ log->Printf ("SBLineEntry(%p)::GetFileSpec () => SBFileSpec(%p): %s",
+ static_cast<void*>(m_opaque_ap.get()),
+ static_cast<const void*>(sb_file_spec.get()),
+ sstr.GetData());
}
-
+
return sb_file_spec;
}
@@ -94,14 +96,15 @@ uint32_t
SBDeclaration::GetLine () const
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
uint32_t line = 0;
if (m_opaque_ap.get())
line = m_opaque_ap->GetLine();
-
+
if (log)
- log->Printf ("SBLineEntry(%p)::GetLine () => %u", m_opaque_ap.get(), line);
-
+ log->Printf ("SBLineEntry(%p)::GetLine () => %u",
+ static_cast<void*>(m_opaque_ap.get()), line);
+
return line;
}
diff --git a/source/API/SBError.cpp b/source/API/SBError.cpp
index bd6b54300f60..157997b2502f 100644
--- a/source/API/SBError.cpp
+++ b/source/API/SBError.cpp
@@ -77,7 +77,8 @@ SBError::Fail () const
ret_value = m_opaque_ap->Fail();
if (log)
- log->Printf ("SBError(%p)::Fail () => %i", m_opaque_ap.get(), ret_value);
+ log->Printf ("SBError(%p)::Fail () => %i",
+ static_cast<void*>(m_opaque_ap.get()), ret_value);
return ret_value;
}
@@ -91,7 +92,8 @@ SBError::Success () const
ret_value = m_opaque_ap->Success();
if (log)
- log->Printf ("SBError(%p)::Success () => %i", m_opaque_ap.get(), ret_value);
+ log->Printf ("SBError(%p)::Success () => %i",
+ static_cast<void*>(m_opaque_ap.get()), ret_value);
return ret_value;
}
@@ -106,7 +108,8 @@ SBError::GetError () const
err = m_opaque_ap->GetError();
if (log)
- log->Printf ("SBError(%p)::GetError () => 0x%8.8x", m_opaque_ap.get(), err);
+ log->Printf ("SBError(%p)::GetError () => 0x%8.8x",
+ static_cast<void*>(m_opaque_ap.get()), err);
return err;
@@ -121,7 +124,8 @@ SBError::GetType () const
err_type = m_opaque_ap->GetType();
if (log)
- log->Printf ("SBError(%p)::GetType () => %i", m_opaque_ap.get(), err_type);
+ log->Printf ("SBError(%p)::GetType () => %i",
+ static_cast<void*>(m_opaque_ap.get()), err_type);
return err_type;
}
diff --git a/source/API/SBEvent.cpp b/source/API/SBEvent.cpp
index d5d4a84bc1fd..57a699fd739d 100644
--- a/source/API/SBEvent.cpp
+++ b/source/API/SBEvent.cpp
@@ -92,9 +92,11 @@ SBEvent::GetType () const
{
StreamString sstr;
if (lldb_event && lldb_event->GetBroadcaster() && lldb_event->GetBroadcaster()->GetEventNames(sstr, event_type, true))
- log->Printf ("SBEvent(%p)::GetType () => 0x%8.8x (%s)", get(), event_type, sstr.GetData());
+ log->Printf ("SBEvent(%p)::GetType () => 0x%8.8x (%s)",
+ static_cast<void*>(get()), event_type, sstr.GetData());
else
- log->Printf ("SBEvent(%p)::GetType () => 0x%8.8x", get(), event_type);
+ log->Printf ("SBEvent(%p)::GetType () => 0x%8.8x",
+ static_cast<void*>(get()), event_type);
}
@@ -141,11 +143,10 @@ SBEvent::BroadcasterMatchesRef (const SBBroadcaster &broadcaster)
// For logging, this gets a little chatty so only enable this when verbose logging is on
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API | LIBLLDB_LOG_VERBOSE));
if (log)
- log->Printf ("SBEvent(%p)::BroadcasterMatchesRef (SBBroadcaster(%p): %s) => %i",
- get(),
- broadcaster.get(),
- broadcaster.GetName(),
- success);
+ log->Printf ("SBEvent(%p)::BroadcasterMatchesRef (SBBroadcaster(%p): %s) => %i",
+ static_cast<void*>(get()),
+ static_cast<void*>(broadcaster.get()),
+ broadcaster.GetName(), success);
return success;
}
@@ -206,8 +207,8 @@ SBEvent::GetCStringFromEvent (const SBEvent &event)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBEvent(%p)::GetCStringFromEvent () => \"%s\"",
- event.get(),
+ log->Printf ("SBEvent(%p)::GetCStringFromEvent () => \"%s\"",
+ static_cast<void*>(event.get()),
reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event.get())));
return reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event.get()));
diff --git a/source/API/SBExpressionOptions.cpp b/source/API/SBExpressionOptions.cpp
index ae1c8f99df30..448ff4cf6dd6 100644
--- a/source/API/SBExpressionOptions.cpp
+++ b/source/API/SBExpressionOptions.cpp
@@ -101,6 +101,18 @@ SBExpressionOptions::SetTimeoutInMicroSeconds (uint32_t timeout)
m_opaque_ap->SetTimeoutUsec (timeout);
}
+uint32_t
+SBExpressionOptions::GetOneThreadTimeoutInMicroSeconds () const
+{
+ return m_opaque_ap->GetOneThreadTimeoutUsec ();
+}
+
+void
+SBExpressionOptions::SetOneThreadTimeoutInMicroSeconds (uint32_t timeout)
+{
+ m_opaque_ap->SetOneThreadTimeoutUsec (timeout);
+}
+
bool
SBExpressionOptions::GetTryAllThreads () const
{
@@ -114,6 +126,18 @@ SBExpressionOptions::SetTryAllThreads (bool run_others)
}
bool
+SBExpressionOptions::GetStopOthers () const
+{
+ return m_opaque_ap->GetStopOthers ();
+}
+
+void
+SBExpressionOptions::SetStopOthers (bool run_others)
+{
+ m_opaque_ap->SetStopOthers (run_others);
+}
+
+bool
SBExpressionOptions::GetTrapExceptions () const
{
return m_opaque_ap->GetTrapExceptions ();
@@ -125,6 +149,43 @@ SBExpressionOptions::SetTrapExceptions (bool trap_exceptions)
m_opaque_ap->SetTrapExceptions (trap_exceptions);
}
+void
+SBExpressionOptions::SetLanguage (lldb::LanguageType language)
+{
+ m_opaque_ap->SetLanguage(language);
+}
+
+void
+SBExpressionOptions::SetCancelCallback (lldb::ExpressionCancelCallback callback, void *baton)
+{
+ m_opaque_ap->SetCancelCallback (callback, baton);
+}
+
+bool
+SBExpressionOptions::GetGenerateDebugInfo ()
+{
+ return m_opaque_ap->GetGenerateDebugInfo();
+}
+
+void
+SBExpressionOptions::SetGenerateDebugInfo (bool b)
+{
+ return m_opaque_ap->SetGenerateDebugInfo(b);
+}
+
+bool
+SBExpressionOptions::GetSuppressPersistentResult ()
+{
+ return m_opaque_ap->GetResultIsInternal ();
+}
+
+void
+SBExpressionOptions::SetSuppressPersistentResult (bool b)
+{
+ return m_opaque_ap->SetResultIsInternal (b);
+}
+
+
EvaluateExpressionOptions *
SBExpressionOptions::get() const
{
diff --git a/source/API/SBFileSpec.cpp b/source/API/SBFileSpec.cpp
index 4fd2866c9b05..8d63fc587d81 100644
--- a/source/API/SBFileSpec.cpp
+++ b/source/API/SBFileSpec.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include <inttypes.h> // PRIu64
#include <limits.h>
#include "lldb/API/SBFileSpec.h"
@@ -15,6 +16,8 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
+#include "llvm/ADT/SmallString.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -35,7 +38,7 @@ SBFileSpec::SBFileSpec (const lldb_private::FileSpec& fspec) :
{
}
-// Deprected!!!
+// Deprecated!!!
SBFileSpec::SBFileSpec (const char *path) :
m_opaque_ap(new FileSpec (path, true))
{
@@ -72,7 +75,9 @@ SBFileSpec::Exists () const
bool result = m_opaque_ap->Exists();
if (log)
- log->Printf ("SBFileSpec(%p)::Exists () => %s", m_opaque_ap.get(), (result ? "true" : "false"));
+ log->Printf ("SBFileSpec(%p)::Exists () => %s",
+ static_cast<void*>(m_opaque_ap.get()),
+ (result ? "true" : "false"));
return result;
}
@@ -86,7 +91,11 @@ SBFileSpec::ResolveExecutableLocation ()
int
SBFileSpec::ResolvePath (const char *src_path, char *dst_path, size_t dst_len)
{
- return lldb_private::FileSpec::Resolve (src_path, dst_path, dst_len);
+ llvm::SmallString<64> result(src_path);
+ lldb_private::FileSpec::Resolve (result);
+ size_t result_length = std::min(dst_len-1, result.size());
+ ::strncpy(dst_path, result.c_str(), result_length + 1);
+ return result_length;
}
const char *
@@ -98,9 +107,11 @@ SBFileSpec::GetFilename() const
if (log)
{
if (s)
- log->Printf ("SBFileSpec(%p)::GetFilename () => \"%s\"", m_opaque_ap.get(), s);
+ log->Printf ("SBFileSpec(%p)::GetFilename () => \"%s\"",
+ static_cast<void*>(m_opaque_ap.get()), s);
else
- log->Printf ("SBFileSpec(%p)::GetFilename () => NULL", m_opaque_ap.get());
+ log->Printf ("SBFileSpec(%p)::GetFilename () => NULL",
+ static_cast<void*>(m_opaque_ap.get()));
}
return s;
@@ -114,9 +125,11 @@ SBFileSpec::GetDirectory() const
if (log)
{
if (s)
- log->Printf ("SBFileSpec(%p)::GetDirectory () => \"%s\"", m_opaque_ap.get(), s);
+ log->Printf ("SBFileSpec(%p)::GetDirectory () => \"%s\"",
+ static_cast<void*>(m_opaque_ap.get()), s);
else
- log->Printf ("SBFileSpec(%p)::GetDirectory () => NULL", m_opaque_ap.get());
+ log->Printf ("SBFileSpec(%p)::GetDirectory () => NULL",
+ static_cast<void*>(m_opaque_ap.get()));
}
return s;
}
@@ -148,7 +161,8 @@ SBFileSpec::GetPath (char *dst_path, size_t dst_len) const
if (log)
log->Printf ("SBFileSpec(%p)::GetPath (dst_path=\"%.*s\", dst_len=%" PRIu64 ") => %u",
- m_opaque_ap.get(), result, dst_path, (uint64_t)dst_len, result);
+ static_cast<void*>(m_opaque_ap.get()), result, dst_path,
+ static_cast<uint64_t>(dst_len), result);
if (result == 0 && dst_path && dst_len > 0)
*dst_path = '\0';
diff --git a/source/API/SBFileSpecList.cpp b/source/API/SBFileSpecList.cpp
index 3ebf3cc80a2a..a457a754f0d0 100644
--- a/source/API/SBFileSpecList.cpp
+++ b/source/API/SBFileSpecList.cpp
@@ -38,7 +38,8 @@ SBFileSpecList::SBFileSpecList (const SBFileSpecList &rhs) :
if (log)
{
log->Printf ("SBFileSpecList::SBFileSpecList (const SBFileSpecList rhs.ap=%p) => SBFileSpecList(%p)",
- rhs.m_opaque_ap.get(), m_opaque_ap.get());
+ static_cast<void*>(rhs.m_opaque_ap.get()),
+ static_cast<void*>(m_opaque_ap.get()));
}
}
diff --git a/source/API/SBFrame.cpp b/source/API/SBFrame.cpp
index 44fc654c44b6..325f40fd5b56 100644
--- a/source/API/SBFrame.cpp
+++ b/source/API/SBFrame.cpp
@@ -63,9 +63,9 @@ SBFrame::SBFrame (const StackFrameSP &lldb_object_sp) :
{
SBStream sstr;
GetDescription (sstr);
- log->Printf ("SBFrame::SBFrame (sp=%p) => SBFrame(%p): %s",
- lldb_object_sp.get(), lldb_object_sp.get(), sstr.GetData());
-
+ log->Printf ("SBFrame::SBFrame (sp=%p) => SBFrame(%p): %s",
+ static_cast<void*>(lldb_object_sp.get()),
+ static_cast<void*>(lldb_object_sp.get()), sstr.GetData());
}
}
@@ -141,8 +141,9 @@ SBFrame::GetSymbolContext (uint32_t resolve_scope) const
}
if (log)
- log->Printf ("SBFrame(%p)::GetSymbolContext (resolve_scope=0x%8.8x) => SBSymbolContext(%p)",
- frame, resolve_scope, sb_sym_ctx.get());
+ log->Printf ("SBFrame(%p)::GetSymbolContext (resolve_scope=0x%8.8x) => SBSymbolContext(%p)",
+ static_cast<void*>(frame), resolve_scope,
+ static_cast<void*>(sb_sym_ctx.get()));
return sb_sym_ctx;
}
@@ -184,8 +185,9 @@ SBFrame::GetModule () const
}
if (log)
- log->Printf ("SBFrame(%p)::GetModule () => SBModule(%p)",
- frame, module_sp.get());
+ log->Printf ("SBFrame(%p)::GetModule () => SBModule(%p)",
+ static_cast<void*>(frame),
+ static_cast<void*>(module_sp.get()));
return sb_module;
}
@@ -224,8 +226,9 @@ SBFrame::GetCompileUnit () const
}
}
if (log)
- log->Printf ("SBFrame(%p)::GetCompileUnit () => SBCompileUnit(%p)",
- frame, sb_comp_unit.get());
+ log->Printf ("SBFrame(%p)::GetCompileUnit () => SBCompileUnit(%p)",
+ static_cast<void*>(frame),
+ static_cast<void*>(sb_comp_unit.get()));
return sb_comp_unit;
}
@@ -264,8 +267,9 @@ SBFrame::GetFunction () const
}
}
if (log)
- log->Printf ("SBFrame(%p)::GetFunction () => SBFunction(%p)",
- frame, sb_function.get());
+ log->Printf ("SBFrame(%p)::GetFunction () => SBFunction(%p)",
+ static_cast<void*>(frame),
+ static_cast<void*>(sb_function.get()));
return sb_function;
}
@@ -304,8 +308,9 @@ SBFrame::GetSymbol () const
}
}
if (log)
- log->Printf ("SBFrame(%p)::GetSymbol () => SBSymbol(%p)",
- frame, sb_symbol.get());
+ log->Printf ("SBFrame(%p)::GetSymbol () => SBSymbol(%p)",
+ static_cast<void*>(frame),
+ static_cast<void*>(sb_symbol.get()));
return sb_symbol;
}
@@ -339,12 +344,14 @@ SBFrame::GetBlock () const
else
{
if (log)
- log->Printf ("SBFrame(%p)::GetBlock () => error: process is running", frame);
+ log->Printf ("SBFrame(%p)::GetBlock () => error: process is running",
+ static_cast<void*>(frame));
}
}
if (log)
- log->Printf ("SBFrame(%p)::GetBlock () => SBBlock(%p)",
- frame, sb_block.GetPtr());
+ log->Printf ("SBFrame(%p)::GetBlock () => SBBlock(%p)",
+ static_cast<void*>(frame),
+ static_cast<void*>(sb_block.GetPtr()));
return sb_block;
}
@@ -382,8 +389,9 @@ SBFrame::GetFrameBlock () const
}
}
if (log)
- log->Printf ("SBFrame(%p)::GetFrameBlock () => SBBlock(%p)",
- frame, sb_block.GetPtr());
+ log->Printf ("SBFrame(%p)::GetFrameBlock () => SBBlock(%p)",
+ static_cast<void*>(frame),
+ static_cast<void*>(sb_block.GetPtr()));
return sb_block;
}
@@ -421,8 +429,9 @@ SBFrame::GetLineEntry () const
}
}
if (log)
- log->Printf ("SBFrame(%p)::GetLineEntry () => SBLineEntry(%p)",
- frame, sb_line_entry.get());
+ log->Printf ("SBFrame(%p)::GetLineEntry () => SBLineEntry(%p)",
+ static_cast<void*>(frame),
+ static_cast<void*>(sb_line_entry.get()));
return sb_line_entry;
}
@@ -430,16 +439,16 @@ uint32_t
SBFrame::GetFrameID () const
{
uint32_t frame_idx = UINT32_MAX;
-
+
ExecutionContext exe_ctx(m_opaque_sp.get());
StackFrame *frame = exe_ctx.GetFramePtr();
if (frame)
frame_idx = frame->GetFrameIndex ();
-
+
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBFrame(%p)::GetFrameID () => %u",
- frame, frame_idx);
+ log->Printf ("SBFrame(%p)::GetFrameID () => %u",
+ static_cast<void*>(frame), frame_idx);
return frame_idx;
}
@@ -478,7 +487,8 @@ SBFrame::GetPC () const
}
if (log)
- log->Printf ("SBFrame(%p)::GetPC () => 0x%" PRIx64, frame, addr);
+ log->Printf ("SBFrame(%p)::GetPC () => 0x%" PRIx64,
+ static_cast<void*>(frame), addr);
return addr;
}
@@ -519,7 +529,7 @@ SBFrame::SetPC (addr_t new_pc)
if (log)
log->Printf ("SBFrame(%p)::SetPC (new_pc=0x%" PRIx64 ") => %i",
- frame, new_pc, ret_val);
+ static_cast<void*>(frame), new_pc, ret_val);
return ret_val;
}
@@ -558,7 +568,8 @@ SBFrame::GetSP () const
}
}
if (log)
- log->Printf ("SBFrame(%p)::GetSP () => 0x%" PRIx64, frame, addr);
+ log->Printf ("SBFrame(%p)::GetSP () => 0x%" PRIx64,
+ static_cast<void*>(frame), addr);
return addr;
}
@@ -599,7 +610,8 @@ SBFrame::GetFP () const
}
if (log)
- log->Printf ("SBFrame(%p)::GetFP () => 0x%" PRIx64, frame, addr);
+ log->Printf ("SBFrame(%p)::GetFP () => 0x%" PRIx64,
+ static_cast<void*>(frame), addr);
return addr;
}
@@ -638,7 +650,9 @@ SBFrame::GetPCAddress () const
}
}
if (log)
- log->Printf ("SBFrame(%p)::GetPCAddress () => SBAddress(%p)", frame, sb_addr.get());
+ log->Printf ("SBFrame(%p)::GetPCAddress () => SBAddress(%p)",
+ static_cast<void*>(frame),
+ static_cast<void*>(sb_addr.get()));
return sb_addr;
}
@@ -727,7 +741,6 @@ SBFrame::FindVariable (const char *name)
}
return value;
}
-
SBValue
SBFrame::FindVariable (const char *name, lldb::DynamicValueType use_dynamic)
@@ -742,7 +755,7 @@ SBFrame::FindVariable (const char *name, lldb::DynamicValueType use_dynamic)
log->Printf ("SBFrame::FindVariable called with empty name");
return sb_value;
}
-
+
ValueObjectSP value_sp;
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
@@ -766,7 +779,7 @@ SBFrame::FindVariable (const char *name, lldb::DynamicValueType use_dynamic)
const bool can_create = true;
const bool get_parent_variables = true;
const bool stop_if_block_is_inlined_function = true;
-
+
if (sc.block->AppendVariables (can_create,
get_parent_variables,
stop_if_block_is_inlined_function,
@@ -794,10 +807,11 @@ SBFrame::FindVariable (const char *name, lldb::DynamicValueType use_dynamic)
log->Printf ("SBFrame::FindVariable () => error: process is running");
}
}
-
+
if (log)
- log->Printf ("SBFrame(%p)::FindVariable (name=\"%s\") => SBValue(%p)",
- frame, name, value_sp.get());
+ log->Printf ("SBFrame(%p)::FindVariable (name=\"%s\") => SBValue(%p)",
+ static_cast<void*>(frame), name,
+ static_cast<void*>(value_sp.get()));
return sb_value;
}
@@ -822,14 +836,14 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy
{
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBValue sb_value;
-
+
if (name == NULL || name[0] == '\0')
{
if (log)
log->Printf ("SBFrame::FindValue called with empty name.");
return sb_value;
}
-
+
ValueObjectSP value_sp;
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
@@ -846,7 +860,7 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy
if (frame)
{
VariableList variable_list;
-
+
switch (value_type)
{
case eValueTypeVariableGlobal: // global variable
@@ -854,7 +868,6 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy
case eValueTypeVariableArgument: // function argument variables
case eValueTypeVariableLocal: // function local variables
{
-
SymbolContext sc (frame->GetSymbolContext (eSymbolContextBlock));
const bool can_create = true;
@@ -957,12 +970,12 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy
log->Printf ("SBFrame::FindValue () => error: process is running");
}
}
-
+
if (log)
- log->Printf ("SBFrame(%p)::FindVariableInScope (name=\"%s\", value_type=%i) => SBValue(%p)",
- frame, name, value_type, value_sp.get());
+ log->Printf ("SBFrame(%p)::FindVariableInScope (name=\"%s\", value_type=%i) => SBValue(%p)",
+ static_cast<void*>(frame), name, value_type,
+ static_cast<void*>(value_sp.get()));
-
return sb_value;
}
@@ -999,10 +1012,9 @@ SBFrame::GetThread () const
{
SBStream sstr;
sb_thread.GetDescription (sstr);
- log->Printf ("SBFrame(%p)::GetThread () => SBThread(%p): %s",
- exe_ctx.GetFramePtr(),
- thread_sp.get(),
- sstr.GetData());
+ log->Printf ("SBFrame(%p)::GetThread () => SBThread(%p): %s",
+ static_cast<void*>(exe_ctx.GetFramePtr()),
+ static_cast<void*>(thread_sp.get()), sstr.GetData());
}
return sb_thread;
@@ -1039,11 +1051,12 @@ SBFrame::Disassemble () const
{
if (log)
log->Printf ("SBFrame::Disassemble () => error: process is running");
- }
+ }
}
if (log)
- log->Printf ("SBFrame(%p)::Disassemble () => %s", frame, disassembly);
+ log->Printf ("SBFrame(%p)::Disassemble () => %s",
+ static_cast<void*>(frame), disassembly);
return disassembly;
}
@@ -1084,12 +1097,9 @@ SBFrame::GetVariables (bool arguments,
Target *target = exe_ctx.GetTargetPtr();
if (log)
- log->Printf ("SBFrame::GetVariables (arguments=%i, locals=%i, statics=%i, in_scope_only=%i)",
- arguments,
- locals,
- statics,
- in_scope_only);
-
+ log->Printf ("SBFrame::GetVariables (arguments=%i, locals=%i, statics=%i, in_scope_only=%i)",
+ arguments, locals, statics, in_scope_only);
+
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
{
@@ -1156,13 +1166,13 @@ SBFrame::GetVariables (bool arguments,
{
if (log)
log->Printf ("SBFrame::GetVariables () => error: process is running");
- }
+ }
}
if (log)
- {
- log->Printf ("SBFrame(%p)::GetVariables (...) => SBValueList(%p)", frame, value_list.opaque_ptr());
- }
+ log->Printf ("SBFrame(%p)::GetVariables (...) => SBValueList(%p)",
+ static_cast<void*>(frame),
+ static_cast<void*>(value_list.opaque_ptr()));
return value_list;
}
@@ -1207,11 +1217,13 @@ SBFrame::GetRegisters ()
{
if (log)
log->Printf ("SBFrame::GetRegisters () => error: process is running");
- }
+ }
}
if (log)
- log->Printf ("SBFrame(%p)::GetRegisters () => SBValueList(%p)", frame, value_list.opaque_ptr());
+ log->Printf ("SBFrame(%p)::GetRegisters () => SBValueList(%p)",
+ static_cast<void*>(frame),
+ static_cast<void*>(value_list.opaque_ptr()));
return value_list;
}
@@ -1265,11 +1277,13 @@ SBFrame::FindRegister (const char *name)
{
if (log)
log->Printf ("SBFrame::FindRegister () => error: process is running");
- }
+ }
}
if (log)
- log->Printf ("SBFrame(%p)::FindRegister () => SBValue(%p)", frame, value_sp.get());
+ log->Printf ("SBFrame(%p)::FindRegister () => SBValue(%p)",
+ static_cast<void*>(frame),
+ static_cast<void*>(value_sp.get()));
return result;
}
@@ -1355,19 +1369,19 @@ lldb::SBValue
SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &options)
{
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
Log *expr_log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- ExecutionResults exe_results = eExecutionSetupError;
+ ExpressionResults exe_results = eExpressionSetupError;
SBValue expr_result;
-
+
if (expr == NULL || expr[0] == '\0')
{
if (log)
log->Printf ("SBFrame::EvaluateExpression called with an empty expression");
return expr_result;
}
-
+
ValueObjectSP expr_value_sp;
Mutex::Locker api_locker;
@@ -1379,7 +1393,7 @@ SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &option
StackFrame *frame = NULL;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
-
+
if (target && process)
{
Process::StopLocker stop_locker;
@@ -1395,7 +1409,7 @@ SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &option
Host::SetCrashDescriptionWithFormat ("SBFrame::EvaluateExpression (expr = \"%s\", fetch_dynamic_value = %u) %s",
expr, options.GetFetchDynamicValue(), frame_description.GetString().c_str());
}
-
+
exe_results = target->EvaluateExpression (expr,
frame,
expr_value_sp,
@@ -1415,21 +1429,18 @@ SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &option
{
if (log)
log->Printf ("SBFrame::EvaluateExpression () => error: process is running");
- }
+ }
}
#ifndef LLDB_DISABLE_PYTHON
if (expr_log)
- expr_log->Printf("** [SBFrame::EvaluateExpression] Expression result is %s, summary %s **",
- expr_result.GetValue(),
- expr_result.GetSummary());
-
+ expr_log->Printf("** [SBFrame::EvaluateExpression] Expression result is %s, summary %s **",
+ expr_result.GetValue(), expr_result.GetSummary());
+
if (log)
- log->Printf ("SBFrame(%p)::EvaluateExpression (expr=\"%s\") => SBValue(%p) (execution result=%d)",
- frame,
- expr,
- expr_value_sp.get(),
- exe_results);
+ log->Printf ("SBFrame(%p)::EvaluateExpression (expr=\"%s\") => SBValue(%p) (execution result=%d)",
+ static_cast<void*>(frame), expr,
+ static_cast<void*>(expr_value_sp.get()), exe_results);
#endif
return expr_result;
diff --git a/source/API/SBFunction.cpp b/source/API/SBFunction.cpp
index bb7ea2e9f202..3d185da17f26 100644
--- a/source/API/SBFunction.cpp
+++ b/source/API/SBFunction.cpp
@@ -66,9 +66,11 @@ SBFunction::GetName() const
if (log)
{
if (cstr)
- log->Printf ("SBFunction(%p)::GetName () => \"%s\"", m_opaque_ptr, cstr);
+ log->Printf ("SBFunction(%p)::GetName () => \"%s\"",
+ static_cast<void*>(m_opaque_ptr), cstr);
else
- log->Printf ("SBFunction(%p)::GetName () => NULL", m_opaque_ptr);
+ log->Printf ("SBFunction(%p)::GetName () => NULL",
+ static_cast<void*>(m_opaque_ptr));
}
return cstr;
}
@@ -83,9 +85,11 @@ SBFunction::GetMangledName () const
if (log)
{
if (cstr)
- log->Printf ("SBFunction(%p)::GetMangledName () => \"%s\"", m_opaque_ptr, cstr);
+ log->Printf ("SBFunction(%p)::GetMangledName () => \"%s\"",
+ static_cast<void*>(m_opaque_ptr), cstr);
else
- log->Printf ("SBFunction(%p)::GetMangledName () => NULL", m_opaque_ptr);
+ log->Printf ("SBFunction(%p)::GetMangledName () => NULL",
+ static_cast<void*>(m_opaque_ptr));
}
return cstr;
}
diff --git a/source/API/SBHostOS.cpp b/source/API/SBHostOS.cpp
index 166403103ad5..ec1e2f2e9cba 100644
--- a/source/API/SBHostOS.cpp
+++ b/source/API/SBHostOS.cpp
@@ -12,6 +12,7 @@
#include "lldb/Host/FileSpec.h"
#include "lldb/Core/Log.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
using namespace lldb;
using namespace lldb_private;
@@ -22,7 +23,7 @@ SBFileSpec
SBHostOS::GetProgramFileSpec ()
{
SBFileSpec sb_filespec;
- sb_filespec.SetFileSpec (Host::GetProgramFileSpec ());
+ sb_filespec.SetFileSpec(HostInfo::GetProgramFileSpec());
return sb_filespec;
}
@@ -31,18 +32,29 @@ SBHostOS::GetLLDBPythonPath ()
{
SBFileSpec sb_lldb_python_filespec;
FileSpec lldb_python_spec;
- if (Host::GetLLDBPath (ePathTypePythonDir, lldb_python_spec))
+ if (HostInfo::GetLLDBPath(ePathTypePythonDir, lldb_python_spec))
{
sb_lldb_python_filespec.SetFileSpec (lldb_python_spec);
}
return sb_lldb_python_filespec;
}
+
+SBFileSpec
+SBHostOS::GetLLDBPath (lldb::PathType path_type)
+{
+ SBFileSpec sb_fspec;
+ FileSpec fspec;
+ if (HostInfo::GetLLDBPath(path_type, fspec))
+ sb_fspec.SetFileSpec (fspec);
+ return sb_fspec;
+}
+
lldb::thread_t
SBHostOS::ThreadCreate
(
const char *name,
- thread_func_t thread_function,
+ lldb::thread_func_t thread_function,
void *thread_arg,
SBError *error_ptr
)
@@ -50,8 +62,10 @@ SBHostOS::ThreadCreate
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBHostOS::ThreadCreate (name=\"%s\", thread_function=%p, thread_arg=%p, error_ptr=%p)", name,
- thread_function, thread_arg, error_ptr);
+ log->Printf ("SBHostOS::ThreadCreate (name=\"%s\", thread_function=%p, thread_arg=%p, error_ptr=%p)",
+ name, reinterpret_cast<void*>(reinterpret_cast<intptr_t>(thread_function)),
+ static_cast<void*>(thread_arg),
+ static_cast<void*>(error_ptr));
// FIXME: You should log the return value?
@@ -77,7 +91,7 @@ SBHostOS::ThreadDetach (lldb::thread_t thread, SBError *error_ptr)
}
bool
-SBHostOS::ThreadJoin (lldb::thread_t thread, thread_result_t *result, SBError *error_ptr)
+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);
}
diff --git a/source/API/SBLineEntry.cpp b/source/API/SBLineEntry.cpp
index 0864a2e006c3..833eea3e35c4 100644
--- a/source/API/SBLineEntry.cpp
+++ b/source/API/SBLineEntry.cpp
@@ -66,7 +66,6 @@ SBLineEntry::~SBLineEntry ()
SBAddress
SBLineEntry::GetStartAddress () const
{
-
SBAddress sb_address;
if (m_opaque_ap.get())
sb_address.SetAddress(&m_opaque_ap->range.GetBaseAddress());
@@ -78,8 +77,9 @@ SBLineEntry::GetStartAddress () const
const Address *addr = sb_address.get();
if (addr)
addr->Dump (&sstr, NULL, Address::DumpStyleModuleWithFileAddress, Address::DumpStyleInvalid, 4);
- log->Printf ("SBLineEntry(%p)::GetStartAddress () => SBAddress (%p): %s",
- m_opaque_ap.get(), sb_address.get(), sstr.GetData());
+ log->Printf ("SBLineEntry(%p)::GetStartAddress () => SBAddress (%p): %s",
+ static_cast<void*>(m_opaque_ap.get()),
+ static_cast<void*>(sb_address.get()), sstr.GetData());
}
return sb_address;
@@ -101,8 +101,9 @@ SBLineEntry::GetEndAddress () const
const Address *addr = sb_address.get();
if (addr)
addr->Dump (&sstr, NULL, Address::DumpStyleModuleWithFileAddress, Address::DumpStyleInvalid, 4);
- log->Printf ("SBLineEntry(%p)::GetEndAddress () => SBAddress (%p): %s",
- m_opaque_ap.get(), sb_address.get(), sstr.GetData());
+ log->Printf ("SBLineEntry(%p)::GetEndAddress () => SBAddress (%p): %s",
+ static_cast<void*>(m_opaque_ap.get()),
+ static_cast<void*>(sb_address.get()), sstr.GetData());
}
return sb_address;
}
@@ -127,8 +128,10 @@ SBLineEntry::GetFileSpec () const
{
SBStream sstr;
sb_file_spec.GetDescription (sstr);
- log->Printf ("SBLineEntry(%p)::GetFileSpec () => SBFileSpec(%p): %s", m_opaque_ap.get(),
- sb_file_spec.get(), sstr.GetData());
+ log->Printf ("SBLineEntry(%p)::GetFileSpec () => SBFileSpec(%p): %s",
+ static_cast<void*>(m_opaque_ap.get()),
+ static_cast<const void*>(sb_file_spec.get()),
+ sstr.GetData());
}
return sb_file_spec;
@@ -144,7 +147,8 @@ SBLineEntry::GetLine () const
line = m_opaque_ap->line;
if (log)
- log->Printf ("SBLineEntry(%p)::GetLine () => %u", m_opaque_ap.get(), line);
+ log->Printf ("SBLineEntry(%p)::GetLine () => %u",
+ static_cast<void*>(m_opaque_ap.get()), line);
return line;
}
diff --git a/source/API/SBListener.cpp b/source/API/SBListener.cpp
index 2e67b4c24e86..bad9ba82bc91 100644
--- a/source/API/SBListener.cpp
+++ b/source/API/SBListener.cpp
@@ -42,7 +42,7 @@ SBListener::SBListener (const char *name) :
if (log)
log->Printf ("SBListener::SBListener (name=\"%s\") => SBListener(%p)",
- name, m_opaque_ptr);
+ name, static_cast<void*>(m_opaque_ptr));
}
@@ -110,7 +110,7 @@ SBListener::StartListeningForEventClass (SBDebugger &debugger,
else
return 0;
}
-
+
bool
SBListener::StopListeningForEventClass (SBDebugger &debugger,
const char *broadcaster_class,
@@ -127,7 +127,7 @@ SBListener::StopListeningForEventClass (SBDebugger &debugger,
else
return false;
}
-
+
uint32_t
SBListener::StartListeningForEvents (const SBBroadcaster& broadcaster, uint32_t event_mask)
{
@@ -136,23 +136,23 @@ SBListener::StartListeningForEvents (const SBBroadcaster& broadcaster, uint32_t
{
acquired_event_mask = m_opaque_ptr->StartListeningForEvents (broadcaster.get(), event_mask);
}
-
+
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
if (log)
{
StreamString sstr_requested;
StreamString sstr_acquired;
-
+
Broadcaster *lldb_broadcaster = broadcaster.get();
if (lldb_broadcaster)
{
const bool got_requested_names = lldb_broadcaster->GetEventNames (sstr_requested, event_mask, false);
const bool got_acquired_names = lldb_broadcaster->GetEventNames (sstr_acquired, acquired_event_mask, false);
log->Printf ("SBListener(%p)::StartListeneingForEvents (SBBroadcaster(%p): %s, event_mask=0x%8.8x%s%s%s) => 0x%8.8x%s%s%s",
- m_opaque_ptr,
- lldb_broadcaster,
- lldb_broadcaster->GetBroadcasterName().GetCString(),
- event_mask,
+ static_cast<void*>(m_opaque_ptr),
+ static_cast<void*>(lldb_broadcaster),
+ lldb_broadcaster->GetBroadcasterName().GetCString(),
+ event_mask,
got_requested_names ? " (" : "",
sstr_requested.GetData(),
got_requested_names ? ")" : "",
@@ -163,12 +163,10 @@ SBListener::StartListeningForEvents (const SBBroadcaster& broadcaster, uint32_t
}
else
{
- log->Printf ("SBListener(%p)::StartListeneingForEvents (SBBroadcaster(%p), event_mask=0x%8.8x) => 0x%8.8x",
- m_opaque_ptr,
- lldb_broadcaster,
- event_mask,
+ log->Printf ("SBListener(%p)::StartListeneingForEvents (SBBroadcaster(%p), event_mask=0x%8.8x) => 0x%8.8x",
+ static_cast<void*>(m_opaque_ptr),
+ static_cast<void*>(lldb_broadcaster), event_mask,
acquired_event_mask);
-
}
}
@@ -194,12 +192,14 @@ SBListener::WaitForEvent (uint32_t timeout_secs, SBEvent &event)
if (timeout_secs == UINT32_MAX)
{
log->Printf ("SBListener(%p)::WaitForEvent (timeout_secs=INFINITE, SBEvent(%p))...",
- m_opaque_ptr, event.get());
+ static_cast<void*>(m_opaque_ptr),
+ static_cast<void*>(event.get()));
}
else
{
log->Printf ("SBListener(%p)::WaitForEvent (timeout_secs=%d, SBEvent(%p))...",
- m_opaque_ptr, timeout_secs, event.get());
+ static_cast<void*>(m_opaque_ptr), timeout_secs,
+ static_cast<void*>(event.get()));
}
}
bool success = false;
@@ -226,12 +226,14 @@ SBListener::WaitForEvent (uint32_t timeout_secs, SBEvent &event)
if (timeout_secs == UINT32_MAX)
{
log->Printf ("SBListener(%p)::WaitForEvent (timeout_secs=INFINITE, SBEvent(%p)) => %i",
- m_opaque_ptr, event.get(), success);
+ static_cast<void*>(m_opaque_ptr),
+ static_cast<void*>(event.get()), success);
}
else
{
log->Printf ("SBListener(%p)::WaitForEvent (timeout_secs=%d, SBEvent(%p)) => %i",
- m_opaque_ptr, timeout_secs, event.get(), success);
+ static_cast<void*>(m_opaque_ptr), timeout_secs,
+ static_cast<void*>(event.get()), success);
}
}
if (!success)
diff --git a/source/API/SBModule.cpp b/source/API/SBModule.cpp
index c8543d4de298..0d7dda1aa1f7 100644
--- a/source/API/SBModule.cpp
+++ b/source/API/SBModule.cpp
@@ -110,10 +110,9 @@ SBModule::GetFileSpec () const
file_spec.SetFileSpec(module_sp->GetFileSpec());
if (log)
- {
- log->Printf ("SBModule(%p)::GetFileSpec () => SBFileSpec(%p)",
- module_sp.get(), file_spec.get());
- }
+ log->Printf ("SBModule(%p)::GetFileSpec () => SBFileSpec(%p)",
+ static_cast<void*>(module_sp.get()),
+ static_cast<const void*>(file_spec.get()));
return file_spec;
}
@@ -122,20 +121,18 @@ lldb::SBFileSpec
SBModule::GetPlatformFileSpec () const
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
SBFileSpec file_spec;
ModuleSP module_sp (GetSP ());
if (module_sp)
file_spec.SetFileSpec(module_sp->GetPlatformFileSpec());
-
+
if (log)
- {
- log->Printf ("SBModule(%p)::GetPlatformFileSpec () => SBFileSpec(%p)",
- module_sp.get(), file_spec.get());
- }
-
+ log->Printf ("SBModule(%p)::GetPlatformFileSpec () => SBFileSpec(%p)",
+ static_cast<void*>(module_sp.get()),
+ static_cast<const void*>(file_spec.get()));
+
return file_spec;
-
}
bool
@@ -143,22 +140,19 @@ SBModule::SetPlatformFileSpec (const lldb::SBFileSpec &platform_file)
{
bool result = false;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
ModuleSP module_sp (GetSP ());
if (module_sp)
{
module_sp->SetPlatformFileSpec(*platform_file);
result = true;
}
-
+
if (log)
- {
- log->Printf ("SBModule(%p)::SetPlatformFileSpec (SBFileSpec(%p (%s)) => %i",
- module_sp.get(),
- platform_file.get(),
- platform_file->GetPath().c_str(),
- result);
- }
+ log->Printf ("SBModule(%p)::SetPlatformFileSpec (SBFileSpec(%p (%s)) => %i",
+ static_cast<void*>(module_sp.get()),
+ static_cast<const void*>(platform_file.get()),
+ platform_file->GetPath().c_str(), result);
return result;
}
@@ -201,10 +195,12 @@ SBModule::GetUUIDBytes () const
{
StreamString s;
module_sp->GetUUID().Dump (&s);
- log->Printf ("SBModule(%p)::GetUUIDBytes () => %s", module_sp.get(), s.GetData());
+ log->Printf ("SBModule(%p)::GetUUIDBytes () => %s",
+ static_cast<void*>(module_sp.get()), s.GetData());
}
else
- log->Printf ("SBModule(%p)::GetUUIDBytes () => NULL", module_sp.get());
+ log->Printf ("SBModule(%p)::GetUUIDBytes () => NULL",
+ static_cast<void*>(module_sp.get()));
}
return uuid_bytes;
}
@@ -225,6 +221,7 @@ SBModule::GetUUIDString () const
if (!uuid_string.empty())
{
strncpy (uuid_string_buffer, uuid_string.c_str(), sizeof (uuid_string_buffer));
+ uuid_string_buffer[sizeof (uuid_string_buffer) - 1] = '\0';
uuid_c_string = uuid_string_buffer;
}
@@ -234,10 +231,12 @@ SBModule::GetUUIDString () const
{
StreamString s;
module_sp->GetUUID().Dump (&s);
- log->Printf ("SBModule(%p)::GetUUIDString () => %s", module_sp.get(), s.GetData());
+ log->Printf ("SBModule(%p)::GetUUIDString () => %s",
+ static_cast<void*>(module_sp.get()), s.GetData());
}
else
- log->Printf ("SBModule(%p)::GetUUIDString () => NULL", module_sp.get());
+ log->Printf ("SBModule(%p)::GetUUIDString () => NULL",
+ static_cast<void*>(module_sp.get()));
}
return uuid_c_string;
}
diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp
index 235388b5f25c..41efd86177d6 100644
--- a/source/API/SBProcess.cpp
+++ b/source/API/SBProcess.cpp
@@ -40,6 +40,7 @@
#include "lldb/API/SBThread.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
+#include "lldb/API/SBUnixSignals.h"
using namespace lldb;
using namespace lldb_private;
@@ -148,20 +149,17 @@ SBProcess::RemoteLaunch (char const **argv,
lldb::SBError& error)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
- if (log) {
+ if (log)
log->Printf ("SBProcess(%p)::RemoteLaunch (argv=%p, envp=%p, stdin=%s, stdout=%s, stderr=%s, working-dir=%s, launch_flags=0x%x, stop_at_entry=%i, &error (%p))...",
- m_opaque_wp.lock().get(),
- argv,
- envp,
- stdin_path ? stdin_path : "NULL",
- stdout_path ? stdout_path : "NULL",
- stderr_path ? stderr_path : "NULL",
+ static_cast<void*>(m_opaque_wp.lock().get()),
+ static_cast<void*>(argv), static_cast<void*>(envp),
+ stdin_path ? stdin_path : "NULL",
+ stdout_path ? stdout_path : "NULL",
+ stderr_path ? stderr_path : "NULL",
working_directory ? working_directory : "NULL",
- launch_flags,
- stop_at_entry,
- error.get());
- }
-
+ launch_flags, stop_at_entry,
+ static_cast<void*>(error.get()));
+
ProcessSP process_sp(GetSP());
if (process_sp)
{
@@ -170,7 +168,7 @@ SBProcess::RemoteLaunch (char const **argv,
{
if (stop_at_entry)
launch_flags |= eLaunchFlagStopAtEntry;
- ProcessLaunchInfo launch_info (stdin_path,
+ ProcessLaunchInfo launch_info (stdin_path,
stdout_path,
stderr_path,
working_directory,
@@ -193,13 +191,15 @@ SBProcess::RemoteLaunch (char const **argv,
{
error.SetErrorString ("unable to attach pid");
}
-
+
if (log) {
SBStream sstr;
error.GetDescription (sstr);
- log->Printf ("SBProcess(%p)::RemoteLaunch (...) => SBError (%p): %s", process_sp.get(), error.get(), sstr.GetData());
+ log->Printf ("SBProcess(%p)::RemoteLaunch (...) => SBError (%p): %s",
+ static_cast<void*>(process_sp.get()),
+ static_cast<void*>(error.get()), sstr.GetData());
}
-
+
return error.Success();
}
@@ -214,7 +214,7 @@ SBProcess::RemoteAttachToProcessWithID (lldb::pid_t pid, lldb::SBError& error)
{
ProcessAttachInfo attach_info;
attach_info.SetProcessID (pid);
- error.SetError (process_sp->Attach (attach_info));
+ error.SetError (process_sp->Attach (attach_info));
}
else
{
@@ -230,7 +230,9 @@ SBProcess::RemoteAttachToProcessWithID (lldb::pid_t pid, lldb::SBError& error)
if (log) {
SBStream sstr;
error.GetDescription (sstr);
- log->Printf ("SBProcess(%p)::RemoteAttachToProcessWithID (%" PRIu64 ") => SBError (%p): %s", process_sp.get(), pid, error.get(), sstr.GetData());
+ log->Printf ("SBProcess(%p)::RemoteAttachToProcessWithID (%" PRIu64 ") => SBError (%p): %s",
+ static_cast<void*>(process_sp.get()), pid,
+ static_cast<void*>(error.get()), sstr.GetData());
}
return error.Success();
@@ -247,14 +249,15 @@ SBProcess::GetNumThreads ()
if (process_sp)
{
Process::StopLocker stop_locker;
-
+
const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock());
Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
num_threads = process_sp->GetThreadList().GetSize(can_update);
}
if (log)
- log->Printf ("SBProcess(%p)::GetNumThreads () => %d", process_sp.get(), num_threads);
+ log->Printf ("SBProcess(%p)::GetNumThreads () => %d",
+ static_cast<void*>(process_sp.get()), num_threads);
return num_threads;
}
@@ -275,9 +278,9 @@ SBProcess::GetSelectedThread () const
}
if (log)
- {
- log->Printf ("SBProcess(%p)::GetSelectedThread () => SBThread(%p)", process_sp.get(), thread_sp.get());
- }
+ log->Printf ("SBProcess(%p)::GetSelectedThread () => SBThread(%p)",
+ static_cast<void*>(process_sp.get()),
+ static_cast<void*>(thread_sp.get()));
return sb_thread;
}
@@ -286,7 +289,7 @@ SBThread
SBProcess::CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
SBThread sb_thread;
ThreadSP thread_sp;
ProcessSP process_sp(GetSP());
@@ -296,10 +299,12 @@ SBProcess::CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context)
thread_sp = process_sp->CreateOSPluginThread(tid, context);
sb_thread.SetThread (thread_sp);
}
-
+
if (log)
- log->Printf ("SBProcess(%p)::CreateOSPluginThread (tid=0x%" PRIx64 ", context=0x%" PRIx64 ") => SBThread(%p)", process_sp.get(), tid, context, thread_sp.get());
-
+ log->Printf ("SBProcess(%p)::CreateOSPluginThread (tid=0x%" PRIx64 ", context=0x%" PRIx64 ") => SBThread(%p)",
+ static_cast<void*>(process_sp.get()), tid, context,
+ static_cast<void*>(thread_sp.get()));
+
return sb_thread;
}
@@ -316,9 +321,11 @@ SBProcess::GetTarget() const
target_sp = process_sp->GetTarget().shared_from_this();
sb_target.SetSP (target_sp);
}
-
+
if (log)
- log->Printf ("SBProcess(%p)::GetTarget () => SBTarget(%p)", process_sp.get(), target_sp.get());
+ log->Printf ("SBProcess(%p)::GetTarget () => SBTarget(%p)",
+ static_cast<void*>(process_sp.get()),
+ static_cast<void*>(target_sp.get()));
return sb_target;
}
@@ -336,13 +343,12 @@ SBProcess::PutSTDIN (const char *src, size_t src_len)
Error error;
ret_val = process_sp->PutSTDIN (src, src_len, error);
}
-
+
if (log)
- log->Printf ("SBProcess(%p)::PutSTDIN (src=\"%s\", src_len=%d) => %zu",
- process_sp.get(),
- src,
- (uint32_t) src_len,
- ret_val);
+ log->Printf("SBProcess(%p)::PutSTDIN (src=\"%s\", src_len=%" PRIu64 ") => %" PRIu64,
+ static_cast<void*>(process_sp.get()), src,
+ static_cast<uint64_t>(src_len),
+ static_cast<uint64_t>(ret_val));
return ret_val;
}
@@ -357,15 +363,14 @@ SBProcess::GetSTDOUT (char *dst, size_t dst_len) const
Error error;
bytes_read = process_sp->GetSTDOUT (dst, dst_len, error);
}
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
log->Printf ("SBProcess(%p)::GetSTDOUT (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64,
- process_sp.get(),
- (int) bytes_read,
- dst,
- (uint64_t)dst_len,
- (uint64_t)bytes_read);
+ static_cast<void*>(process_sp.get()),
+ static_cast<int>(bytes_read), dst,
+ static_cast<uint64_t>(dst_len),
+ static_cast<uint64_t>(bytes_read));
return bytes_read;
}
@@ -384,11 +389,10 @@ SBProcess::GetSTDERR (char *dst, size_t dst_len) const
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
log->Printf ("SBProcess(%p)::GetSTDERR (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64,
- process_sp.get(),
- (int) bytes_read,
- dst,
- (uint64_t)dst_len,
- (uint64_t)bytes_read);
+ static_cast<void*>(process_sp.get()),
+ static_cast<int>(bytes_read), dst,
+ static_cast<uint64_t>(dst_len),
+ static_cast<uint64_t>(bytes_read));
return bytes_read;
}
@@ -403,16 +407,15 @@ SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const
Error error;
bytes_read = process_sp->GetAsyncProfileData (dst, dst_len, error);
}
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
log->Printf ("SBProcess(%p)::GetProfileData (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64,
- process_sp.get(),
- (int) bytes_read,
- dst,
- (uint64_t)dst_len,
- (uint64_t)bytes_read);
-
+ static_cast<void*>(process_sp.get()),
+ static_cast<int>(bytes_read), dst,
+ static_cast<uint64_t>(dst_len),
+ static_cast<uint64_t>(bytes_read));
+
return bytes_read;
}
@@ -483,7 +486,8 @@ SBProcess::SetSelectedThreadByID (lldb::tid_t tid)
if (log)
log->Printf ("SBProcess(%p)::SetSelectedThreadByID (tid=0x%4.4" PRIx64 ") => %s",
- process_sp.get(), tid, (ret_val ? "true" : "false"));
+ static_cast<void*>(process_sp.get()), tid,
+ (ret_val ? "true" : "false"));
return ret_val;
}
@@ -502,8 +506,9 @@ SBProcess::SetSelectedThreadByIndexID (uint32_t index_id)
}
if (log)
- log->Printf ("SBProcess(%p)::SetSelectedThreadByID (tid=0x%x) => %s",
- process_sp.get(), index_id, (ret_val ? "true" : "false"));
+ log->Printf ("SBProcess(%p)::SetSelectedThreadByID (tid=0x%x) => %s",
+ static_cast<void*>(process_sp.get()), index_id,
+ (ret_val ? "true" : "false"));
return ret_val;
}
@@ -526,10 +531,10 @@ SBProcess::GetThreadAtIndex (size_t index)
}
if (log)
- {
log->Printf ("SBProcess(%p)::GetThreadAtIndex (index=%d) => SBThread(%p)",
- process_sp.get(), (uint32_t) index, thread_sp.get());
- }
+ static_cast<void*>(process_sp.get()),
+ static_cast<uint32_t>(index),
+ static_cast<void*>(thread_sp.get()));
return sb_thread;
}
@@ -544,13 +549,14 @@ SBProcess::GetNumQueues ()
if (process_sp)
{
Process::StopLocker stop_locker;
-
+
Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
num_queues = process_sp->GetQueueList().GetSize();
}
if (log)
- log->Printf ("SBProcess(%p)::GetNumQueues () => %d", process_sp.get(), num_queues);
+ log->Printf ("SBProcess(%p)::GetNumQueues () => %d",
+ static_cast<void*>(process_sp.get()), num_queues);
return num_queues;
}
@@ -572,10 +578,10 @@ SBProcess::GetQueueAtIndex (size_t index)
}
if (log)
- {
log->Printf ("SBProcess(%p)::GetQueueAtIndex (index=%d) => SBQueue(%p)",
- process_sp.get(), (uint32_t) index, queue_sp.get());
- }
+ static_cast<void*>(process_sp.get()),
+ static_cast<uint32_t>(index),
+ static_cast<void*>(queue_sp.get()));
return sb_queue;
}
@@ -610,8 +616,8 @@ SBProcess::GetState ()
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::GetState () => %s",
- process_sp.get(),
+ log->Printf ("SBProcess(%p)::GetState () => %s",
+ static_cast<void*>(process_sp.get()),
lldb_private::StateAsCString (ret_val));
return ret_val;
@@ -630,8 +636,9 @@ SBProcess::GetExitStatus ()
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::GetExitStatus () => %i (0x%8.8x)",
- process_sp.get(), exit_status, exit_status);
+ log->Printf ("SBProcess(%p)::GetExitStatus () => %i (0x%8.8x)",
+ static_cast<void*>(process_sp.get()), exit_status,
+ exit_status);
return exit_status;
}
@@ -648,8 +655,8 @@ SBProcess::GetExitDescription ()
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::GetExitDescription () => %s",
- process_sp.get(), exit_desc);
+ log->Printf ("SBProcess(%p)::GetExitDescription () => %s",
+ static_cast<void*>(process_sp.get()), exit_desc);
return exit_desc;
}
@@ -663,7 +670,8 @@ SBProcess::GetProcessID ()
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::GetProcessID () => %" PRIu64, process_sp.get(), ret_val);
+ log->Printf ("SBProcess(%p)::GetProcessID () => %" PRIu64,
+ static_cast<void*>(process_sp.get()), ret_val);
return ret_val;
}
@@ -677,7 +685,8 @@ SBProcess::GetUniqueID()
ret_val = process_sp->GetUniqueID();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::GetUniqueID () => %" PRIu32, process_sp.get(), ret_val);
+ log->Printf ("SBProcess(%p)::GetUniqueID () => %" PRIu32,
+ static_cast<void*>(process_sp.get()), ret_val);
return ret_val;
}
@@ -688,10 +697,11 @@ SBProcess::GetByteOrder () const
ProcessSP process_sp(GetSP());
if (process_sp)
byteOrder = process_sp->GetTarget().GetArchitecture().GetByteOrder();
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::GetByteOrder () => %d", process_sp.get(), byteOrder);
+ log->Printf ("SBProcess(%p)::GetByteOrder () => %d",
+ static_cast<void*>(process_sp.get()), byteOrder);
return byteOrder;
}
@@ -706,7 +716,8 @@ SBProcess::GetAddressByteSize () const
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::GetAddressByteSize () => %d", process_sp.get(), size);
+ log->Printf ("SBProcess(%p)::GetAddressByteSize () => %d",
+ static_cast<void*>(process_sp.get()), size);
return size;
}
@@ -715,24 +726,26 @@ SBError
SBProcess::Continue ()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
SBError sb_error;
ProcessSP process_sp(GetSP());
if (log)
- log->Printf ("SBProcess(%p)::Continue ()...", process_sp.get());
+ log->Printf ("SBProcess(%p)::Continue ()...",
+ static_cast<void*>(process_sp.get()));
if (process_sp)
{
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...", process_sp.get());
+ log->Printf ("SBProcess(%p)::Continue () waiting for process to stop...",
+ static_cast<void*>(process_sp.get()));
process_sp->WaitForProcessToStop (NULL);
}
}
@@ -745,7 +758,9 @@ SBProcess::Continue ()
{
SBStream sstr;
sb_error.GetDescription (sstr);
- log->Printf ("SBProcess(%p)::Continue () => SBError (%p): %s", process_sp.get(), sb_error.get(), sstr.GetData());
+ log->Printf ("SBProcess(%p)::Continue () => SBError (%p): %s",
+ static_cast<void*>(process_sp.get()),
+ static_cast<void*>(sb_error.get()), sstr.GetData());
}
return sb_error;
@@ -770,10 +785,9 @@ SBProcess::Destroy ()
{
SBStream sstr;
sb_error.GetDescription (sstr);
- log->Printf ("SBProcess(%p)::Destroy () => SBError (%p): %s",
- process_sp.get(),
- sb_error.get(),
- sstr.GetData());
+ log->Printf ("SBProcess(%p)::Destroy () => SBError (%p): %s",
+ static_cast<void*>(process_sp.get()),
+ static_cast<void*>(sb_error.get()), sstr.GetData());
}
return sb_error;
@@ -792,16 +806,15 @@ SBProcess::Stop ()
}
else
sb_error.SetErrorString ("SBProcess is invalid");
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
{
SBStream sstr;
sb_error.GetDescription (sstr);
- log->Printf ("SBProcess(%p)::Stop () => SBError (%p): %s",
- process_sp.get(),
- sb_error.get(),
- sstr.GetData());
+ log->Printf ("SBProcess(%p)::Stop () => SBError (%p): %s",
+ static_cast<void*>(process_sp.get()),
+ static_cast<void*>(sb_error.get()), sstr.GetData());
}
return sb_error;
@@ -825,10 +838,9 @@ SBProcess::Kill ()
{
SBStream sstr;
sb_error.GetDescription (sstr);
- log->Printf ("SBProcess(%p)::Kill () => SBError (%p): %s",
- process_sp.get(),
- sb_error.get(),
- sstr.GetData());
+ log->Printf ("SBProcess(%p)::Kill () => SBError (%p): %s",
+ static_cast<void*>(process_sp.get()),
+ static_cast<void*>(sb_error.get()), sstr.GetData());
}
return sb_error;
@@ -869,21 +881,32 @@ SBProcess::Signal (int signo)
sb_error.SetError (process_sp->Signal (signo));
}
else
- sb_error.SetErrorString ("SBProcess is invalid");
+ sb_error.SetErrorString ("SBProcess is invalid");
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
{
SBStream sstr;
sb_error.GetDescription (sstr);
- log->Printf ("SBProcess(%p)::Signal (signo=%i) => SBError (%p): %s",
- process_sp.get(),
- signo,
- sb_error.get(),
- sstr.GetData());
+ log->Printf ("SBProcess(%p)::Signal (signo=%i) => SBError (%p): %s",
+ static_cast<void*>(process_sp.get()), signo,
+ static_cast<void*>(sb_error.get()), sstr.GetData());
}
return sb_error;
}
+SBUnixSignals
+SBProcess::GetUnixSignals()
+{
+ SBUnixSignals sb_unix_signals;
+ ProcessSP process_sp(GetSP());
+ if (process_sp)
+ {
+ sb_unix_signals.SetSP(process_sp);
+ }
+
+ return sb_unix_signals;
+}
+
void
SBProcess::SendAsyncInterrupt ()
{
@@ -911,12 +934,9 @@ SBProcess::GetThreadByID (tid_t tid)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- {
log->Printf ("SBProcess(%p)::GetThreadByID (tid=0x%4.4" PRIx64 ") => SBThread (%p)",
- process_sp.get(),
- tid,
- thread_sp.get());
- }
+ static_cast<void*>(process_sp.get()), tid,
+ static_cast<void*>(thread_sp.get()));
return sb_thread;
}
@@ -938,12 +958,9 @@ SBProcess::GetThreadByIndexID (uint32_t index_id)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- {
- log->Printf ("SBProcess(%p)::GetThreadByID (tid=0x%x) => SBThread (%p)",
- process_sp.get(),
- index_id,
- thread_sp.get());
- }
+ log->Printf ("SBProcess(%p)::GetThreadByID (tid=0x%x) => SBThread (%p)",
+ static_cast<void*>(process_sp.get()), index_id,
+ static_cast<void*>(thread_sp.get()));
return sb_thread;
}
@@ -954,9 +971,10 @@ SBProcess::GetStateFromEvent (const SBEvent &event)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
StateType ret_val = Process::ProcessEventData::GetStateFromEvent (event.get());
-
+
if (log)
- log->Printf ("SBProcess::GetStateFromEvent (event.sp=%p) => %s", event.get(),
+ log->Printf ("SBProcess::GetStateFromEvent (event.sp=%p) => %s",
+ static_cast<void*>(event.get()),
lldb_private::StateAsCString (ret_val));
return ret_val;
@@ -1003,8 +1021,9 @@ SBProcess::GetBroadcaster () const
SBBroadcaster broadcaster(process_sp.get(), false);
if (log)
- log->Printf ("SBProcess(%p)::GetBroadcaster () => SBBroadcaster (%p)", process_sp.get(),
- broadcaster.get());
+ log->Printf ("SBProcess(%p)::GetBroadcaster () => SBBroadcaster (%p)",
+ static_cast<void*>(process_sp.get()),
+ static_cast<void*>(broadcaster.get()));
return broadcaster;
}
@@ -1025,15 +1044,11 @@ SBProcess::ReadMemory (addr_t addr, void *dst, size_t dst_len, SBError &sb_error
ProcessSP process_sp(GetSP());
if (log)
- {
log->Printf ("SBProcess(%p)::ReadMemory (addr=0x%" PRIx64 ", dst=%p, dst_len=%" PRIu64 ", SBError (%p))...",
- process_sp.get(),
- addr,
- dst,
- (uint64_t)dst_len,
- sb_error.get());
- }
-
+ static_cast<void*>(process_sp.get()), addr,
+ static_cast<void*>(dst), static_cast<uint64_t>(dst_len),
+ static_cast<void*>(sb_error.get()));
+
if (process_sp)
{
Process::StopLocker stop_locker;
@@ -1045,7 +1060,8 @@ SBProcess::ReadMemory (addr_t addr, void *dst, size_t dst_len, SBError &sb_error
else
{
if (log)
- log->Printf ("SBProcess(%p)::ReadMemory() => error: process is running", process_sp.get());
+ log->Printf ("SBProcess(%p)::ReadMemory() => error: process is running",
+ static_cast<void*>(process_sp.get()));
sb_error.SetErrorString("process is running");
}
}
@@ -1059,13 +1075,10 @@ SBProcess::ReadMemory (addr_t addr, void *dst, size_t dst_len, SBError &sb_error
SBStream sstr;
sb_error.GetDescription (sstr);
log->Printf ("SBProcess(%p)::ReadMemory (addr=0x%" PRIx64 ", dst=%p, dst_len=%" PRIu64 ", SBError (%p): %s) => %" PRIu64,
- process_sp.get(),
- addr,
- dst,
- (uint64_t)dst_len,
- sb_error.get(),
- sstr.GetData(),
- (uint64_t)bytes_read);
+ static_cast<void*>(process_sp.get()), addr,
+ static_cast<void*>(dst), static_cast<uint64_t>(dst_len),
+ static_cast<void*>(sb_error.get()), sstr.GetData(),
+ static_cast<uint64_t>(bytes_read));
}
return bytes_read;
@@ -1088,7 +1101,8 @@ SBProcess::ReadCStringFromMemory (addr_t addr, void *buf, size_t size, lldb::SBE
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::ReadCStringFromMemory() => error: process is running", process_sp.get());
+ log->Printf ("SBProcess(%p)::ReadCStringFromMemory() => error: process is running",
+ static_cast<void*>(process_sp.get()));
sb_error.SetErrorString("process is running");
}
}
@@ -1116,7 +1130,8 @@ SBProcess::ReadUnsignedFromMemory (addr_t addr, uint32_t byte_size, lldb::SBErro
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::ReadUnsignedFromMemory() => error: process is running", process_sp.get());
+ log->Printf ("SBProcess(%p)::ReadUnsignedFromMemory() => error: process is running",
+ static_cast<void*>(process_sp.get()));
sb_error.SetErrorString("process is running");
}
}
@@ -1144,7 +1159,8 @@ SBProcess::ReadPointerFromMemory (addr_t addr, lldb::SBError &sb_error)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::ReadPointerFromMemory() => error: process is running", process_sp.get());
+ log->Printf ("SBProcess(%p)::ReadPointerFromMemory() => error: process is running",
+ static_cast<void*>(process_sp.get()));
sb_error.SetErrorString("process is running");
}
}
@@ -1165,14 +1181,11 @@ SBProcess::WriteMemory (addr_t addr, const void *src, size_t src_len, SBError &s
ProcessSP process_sp(GetSP());
if (log)
- {
log->Printf ("SBProcess(%p)::WriteMemory (addr=0x%" PRIx64 ", src=%p, src_len=%" PRIu64 ", SBError (%p))...",
- process_sp.get(),
- addr,
- src,
- (uint64_t)src_len,
- sb_error.get());
- }
+ static_cast<void*>(process_sp.get()), addr,
+ static_cast<const void*>(src),
+ static_cast<uint64_t>(src_len),
+ static_cast<void*>(sb_error.get()));
if (process_sp)
{
@@ -1185,7 +1198,8 @@ SBProcess::WriteMemory (addr_t addr, const void *src, size_t src_len, SBError &s
else
{
if (log)
- log->Printf ("SBProcess(%p)::WriteMemory() => error: process is running", process_sp.get());
+ log->Printf ("SBProcess(%p)::WriteMemory() => error: process is running",
+ static_cast<void*>(process_sp.get()));
sb_error.SetErrorString("process is running");
}
}
@@ -1195,13 +1209,11 @@ SBProcess::WriteMemory (addr_t addr, const void *src, size_t src_len, SBError &s
SBStream sstr;
sb_error.GetDescription (sstr);
log->Printf ("SBProcess(%p)::WriteMemory (addr=0x%" PRIx64 ", src=%p, src_len=%" PRIu64 ", SBError (%p): %s) => %" PRIu64,
- process_sp.get(),
- addr,
- src,
- (uint64_t)src_len,
- sb_error.get(),
- sstr.GetData(),
- (uint64_t)bytes_written);
+ static_cast<void*>(process_sp.get()), addr,
+ static_cast<const void*>(src),
+ static_cast<uint64_t>(src_len),
+ static_cast<void*>(sb_error.get()), sstr.GetData(),
+ static_cast<uint64_t>(bytes_written));
}
return bytes_written;
@@ -1248,7 +1260,7 @@ SBProcess::GetNumSupportedHardwareWatchpoints (lldb::SBError &sb_error) const
sb_error.SetError(process_sp->GetWatchpointSupportInfo (num));
if (log)
log->Printf ("SBProcess(%p)::GetNumSupportedHardwareWatchpoints () => %u",
- process_sp.get(), num);
+ static_cast<void*>(process_sp.get()), num);
}
else
{
@@ -1273,13 +1285,14 @@ SBProcess::LoadImage (lldb::SBFileSpec &sb_image_spec, lldb::SBError &sb_error)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::LoadImage() => error: process is running", process_sp.get());
+ log->Printf ("SBProcess(%p)::LoadImage() => error: process is running",
+ static_cast<void*>(process_sp.get()));
sb_error.SetErrorString("process is running");
}
}
return LLDB_INVALID_IMAGE_TOKEN;
}
-
+
lldb::SBError
SBProcess::UnloadImage (uint32_t image_token)
{
@@ -1297,7 +1310,35 @@ SBProcess::UnloadImage (uint32_t image_token)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::UnloadImage() => error: process is running", process_sp.get());
+ log->Printf ("SBProcess(%p)::UnloadImage() => error: process is running",
+ static_cast<void*>(process_sp.get()));
+ sb_error.SetErrorString("process is running");
+ }
+ }
+ else
+ sb_error.SetErrorString("invalid process");
+ return sb_error;
+}
+
+lldb::SBError
+SBProcess::SendEventData (const char *event_data)
+{
+ lldb::SBError sb_error;
+ ProcessSP process_sp(GetSP());
+ if (process_sp)
+ {
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&process_sp->GetRunLock()))
+ {
+ Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
+ sb_error.SetError (process_sp->SendEventData (event_data));
+ }
+ else
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf ("SBProcess(%p)::SendEventData() => error: process is running",
+ static_cast<void*>(process_sp.get()));
sb_error.SetErrorString("process is running");
}
}
@@ -1334,7 +1375,8 @@ SBProcess::GetExtendedBacktraceTypeAtIndex (uint32_t idx)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf("SBProcess(%p)::GetExtendedBacktraceTypeAtIndex() => error: requested extended backtrace name out of bounds", process_sp.get());
+ log->Printf("SBProcess(%p)::GetExtendedBacktraceTypeAtIndex() => error: requested extended backtrace name out of bounds",
+ static_cast<void*>(process_sp.get()));
}
}
return NULL;
diff --git a/source/API/SBQueue.cpp b/source/API/SBQueue.cpp
index 8d67a48d6b81..b19ed72543c2 100644
--- a/source/API/SBQueue.cpp
+++ b/source/API/SBQueue.cpp
@@ -9,10 +9,14 @@
#include "lldb/lldb-python.h"
+#include <inttypes.h>
+
#include "lldb/API/SBQueue.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBThread.h"
+#include "lldb/API/SBQueueItem.h"
+
#include "lldb/Core/Log.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Queue.h"
@@ -96,7 +100,8 @@ namespace lldb_private
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBQueue(%p)::GetQueueID () => 0x%" PRIx64, this, result);
+ log->Printf ("SBQueue(%p)::GetQueueID () => 0x%" PRIx64,
+ static_cast<const void*>(this), result);
return result;
}
@@ -111,10 +116,11 @@ namespace lldb_private
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBQueueImpl(%p)::GetIndexID () => %d", this, result);
+ log->Printf ("SBQueueImpl(%p)::GetIndexID () => %d",
+ static_cast<const void*>(this), result);
return result;
}
-
+
const char *
GetName () const
{
@@ -124,14 +130,16 @@ namespace lldb_private
{
name = queue_sp->GetName();
}
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBQueueImpl(%p)::GetName () => %s", this, name ? name : "NULL");
-
+ log->Printf ("SBQueueImpl(%p)::GetName () => %s",
+ static_cast<const void*>(this),
+ name ? name : "NULL");
+
return name;
}
-
+
void
FetchThreads ()
{
@@ -158,7 +166,7 @@ namespace lldb_private
}
}
}
-
+
void
FetchItems ()
{
@@ -185,12 +193,12 @@ namespace lldb_private
}
}
}
-
+
uint32_t
GetNumThreads ()
{
uint32_t result = 0;
-
+
FetchThreads();
if (m_thread_list_fetched)
{
@@ -198,12 +206,12 @@ namespace lldb_private
}
return result;
}
-
+
lldb::SBThread
GetThreadAtIndex (uint32_t idx)
{
FetchThreads();
-
+
SBThread sb_thread;
QueueSP queue_sp = m_queue_wp.lock();
if (queue_sp && idx < m_threads.size())
@@ -220,21 +228,24 @@ namespace lldb_private
}
return sb_thread;
}
-
-
+
uint32_t
GetNumPendingItems ()
{
uint32_t result = 0;
- FetchItems();
-
- if (m_pending_items_fetched)
+
+ QueueSP queue_sp = m_queue_wp.lock();
+ if (m_pending_items_fetched == false && queue_sp)
+ {
+ result = queue_sp->GetNumPendingWorkItems();
+ }
+ else
{
result = m_pending_items.size();
}
return result;
}
-
+
lldb::SBQueueItem
GetPendingItemAtIndex (uint32_t idx)
{
@@ -246,7 +257,17 @@ namespace lldb_private
}
return result;
}
-
+
+ uint32_t
+ GetNumRunningItems ()
+ {
+ uint32_t result = 0;
+ QueueSP queue_sp = m_queue_wp.lock();
+ if (queue_sp)
+ result = queue_sp->GetNumRunningWorkItems();
+ return result;
+ }
+
lldb::SBProcess
GetProcess ()
{
@@ -259,6 +280,17 @@ namespace lldb_private
return result;
}
+ lldb::QueueKind
+ GetKind ()
+ {
+ lldb::QueueKind kind = eQueueKindUnknown;
+ QueueSP queue_sp = m_queue_wp.lock();
+ if (queue_sp)
+ kind = queue_sp->GetKind();
+
+ return kind;
+ }
+
private:
lldb::QueueWP m_queue_wp;
std::vector<lldb::ThreadWP> m_threads; // threads currently executing this queue's items
@@ -301,13 +333,21 @@ SBQueue::~SBQueue()
bool
SBQueue::IsValid() const
{
- return m_opaque_sp->IsValid();
+ bool is_valid = m_opaque_sp->IsValid ();
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBQueue(0x%" PRIx64 ")::IsValid() == %s", m_opaque_sp->GetQueueID(),
+ is_valid ? "true" : "false");
+ return is_valid;
}
void
SBQueue::Clear ()
{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBQueue(0x%" PRIx64 ")::Clear()", m_opaque_sp->GetQueueID());
m_opaque_sp->Clear();
}
@@ -321,48 +361,92 @@ SBQueue::SetQueue (const QueueSP& queue_sp)
lldb::queue_id_t
SBQueue::GetQueueID () const
{
- return m_opaque_sp->GetQueueID ();
+ lldb::queue_id_t qid = m_opaque_sp->GetQueueID ();
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBQueue(0x%" PRIx64 ")::GetQueueID() == 0x%" PRIx64, m_opaque_sp->GetQueueID(), (uint64_t) qid);
+ return qid;
}
uint32_t
SBQueue::GetIndexID () const
{
- return m_opaque_sp->GetIndexID ();
+ uint32_t index_id = m_opaque_sp->GetIndexID ();
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBQueue(0x%" PRIx64 ")::GetIndexID() == 0x%" PRIx32, m_opaque_sp->GetQueueID(), index_id);
+ return index_id;
}
const char *
SBQueue::GetName () const
{
- return m_opaque_sp->GetName ();
+ const char *name = m_opaque_sp->GetName ();
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBQueue(0x%" PRIx64 ")::GetName() == %s", m_opaque_sp->GetQueueID(),
+ name ? name : "");
+ return name;
}
uint32_t
SBQueue::GetNumThreads ()
{
- return m_opaque_sp->GetNumThreads ();
+ uint32_t numthreads = m_opaque_sp->GetNumThreads ();
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBQueue(0x%" PRIx64 ")::GetNumThreads() == %d", m_opaque_sp->GetQueueID(), numthreads);
+ return numthreads;
}
SBThread
SBQueue::GetThreadAtIndex (uint32_t idx)
{
- return m_opaque_sp->GetThreadAtIndex (idx);
+ SBThread th = m_opaque_sp->GetThreadAtIndex (idx);
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBQueue(0x%" PRIx64 ")::GetThreadAtIndex(%d)", m_opaque_sp->GetQueueID(), idx);
+ return th;
}
uint32_t
SBQueue::GetNumPendingItems ()
{
- return m_opaque_sp->GetNumPendingItems ();
+ uint32_t pending_items = m_opaque_sp->GetNumPendingItems ();
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBQueue(0x%" PRIx64 ")::GetNumPendingItems() == %d", m_opaque_sp->GetQueueID(), pending_items);
+ return pending_items;
}
SBQueueItem
SBQueue::GetPendingItemAtIndex (uint32_t idx)
{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBQueue(0x%" PRIx64 ")::GetPendingItemAtIndex(%d)", m_opaque_sp->GetQueueID(), idx);
return m_opaque_sp->GetPendingItemAtIndex (idx);
}
+uint32_t
+SBQueue::GetNumRunningItems ()
+{
+ uint32_t running_items = m_opaque_sp->GetNumRunningItems ();
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBQueue(0x%" PRIx64 ")::GetNumRunningItems() == %d", m_opaque_sp->GetQueueID(), running_items);
+ return running_items;
+}
+
SBProcess
SBQueue::GetProcess ()
{
return m_opaque_sp->GetProcess();
}
+
+lldb::QueueKind
+SBQueue::GetKind ()
+{
+ return m_opaque_sp->GetKind();
+}
diff --git a/source/API/SBQueueItem.cpp b/source/API/SBQueueItem.cpp
index 481d51e55426..6a1aa7bec61a 100644
--- a/source/API/SBQueueItem.cpp
+++ b/source/API/SBQueueItem.cpp
@@ -14,6 +14,8 @@
#include "lldb/API/SBQueueItem.h"
#include "lldb/API/SBThread.h"
#include "lldb/Core/Address.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/QueueItem.h"
#include "lldb/Target/Thread.h"
@@ -44,13 +46,23 @@ SBQueueItem::~SBQueueItem()
bool
SBQueueItem::IsValid() const
{
- return m_queue_item_sp.get() != NULL;
+ bool is_valid = m_queue_item_sp.get() != NULL;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBQueueItem(%p)::IsValid() == %s",
+ static_cast<void*>(m_queue_item_sp.get()),
+ is_valid ? "true" : "false");
+ return is_valid;
}
void
SBQueueItem::Clear ()
{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBQueueItem(%p)::Clear()",
+ static_cast<void*>(m_queue_item_sp.get()));
m_queue_item_sp.reset();
}
@@ -66,10 +78,15 @@ lldb::QueueItemKind
SBQueueItem::GetKind () const
{
QueueItemKind result = eQueueItemKindUnknown;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (m_queue_item_sp)
{
result = m_queue_item_sp->GetKind ();
}
+ if (log)
+ log->Printf("SBQueueItem(%p)::GetKind() == %d",
+ static_cast<void*>(m_queue_item_sp.get()),
+ static_cast<int>(result));
return result;
}
@@ -86,10 +103,21 @@ SBAddress
SBQueueItem::GetAddress () const
{
SBAddress result;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (m_queue_item_sp)
{
result.SetAddress (&m_queue_item_sp->GetAddress());
}
+ if (log)
+ {
+ StreamString sstr;
+ const Address *addr = result.get();
+ if (addr)
+ addr->Dump (&sstr, NULL, Address::DumpStyleModuleWithFileAddress, Address::DumpStyleInvalid, 4);
+ log->Printf ("SBQueueItem(%p)::GetAddress() == SBAddress(%p): %s",
+ static_cast<void*>(m_queue_item_sp.get()),
+ static_cast<void*>(result.get()), sstr.GetData());
+ }
return result;
}
@@ -106,14 +134,34 @@ SBThread
SBQueueItem::GetExtendedBacktraceThread (const char *type)
{
SBThread result;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (m_queue_item_sp)
{
- ThreadSP thread_sp;
- ConstString type_const (type);
- thread_sp = m_queue_item_sp->GetExtendedBacktraceThread (type_const);
- if (thread_sp)
+ ProcessSP process_sp = m_queue_item_sp->GetProcessSP();
+ Process::StopLocker stop_locker;
+ if (process_sp && stop_locker.TryLock(&process_sp->GetRunLock()))
{
- result.SetThread (thread_sp);
+ ThreadSP thread_sp;
+ ConstString type_const (type);
+ thread_sp = m_queue_item_sp->GetExtendedBacktraceThread (type_const);
+ if (thread_sp)
+ {
+ // Save this in the Process' ExtendedThreadList so a strong pointer retains the
+ // object
+ process_sp->GetExtendedThreadList().AddThread (thread_sp);
+ result.SetThread (thread_sp);
+ if (log)
+ {
+ const char *queue_name = thread_sp->GetQueueName();
+ if (queue_name == NULL)
+ queue_name = "";
+ log->Printf ("SBQueueItem(%p)::GetExtendedBacktraceThread() = new extended Thread created (%p) with queue_id 0x%" PRIx64 " queue name '%s'",
+ static_cast<void*>(m_queue_item_sp.get()),
+ static_cast<void*>(thread_sp.get()),
+ static_cast<uint64_t>(thread_sp->GetQueueID()),
+ queue_name);
+ }
+ }
}
}
return result;
diff --git a/source/API/SBStream.cpp b/source/API/SBStream.cpp
index 531ab9f463ce..f5b5c08411c7 100644
--- a/source/API/SBStream.cpp
+++ b/source/API/SBStream.cpp
@@ -82,6 +82,8 @@ SBStream::RedirectToFile (const char *path, bool append)
uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
if (append)
open_options |= File::eOpenOptionAppend;
+ else
+ open_options |= File::eOpenOptionTruncate;
stream_file->GetFile().Open (path, open_options, lldb::eFilePermissionsFileDefault);
m_opaque_ap.reset (stream_file);
diff --git a/source/API/SBSymbol.cpp b/source/API/SBSymbol.cpp
index ef3d0764c963..12a3b317d501 100644
--- a/source/API/SBSymbol.cpp
+++ b/source/API/SBSymbol.cpp
@@ -67,7 +67,8 @@ SBSymbol::GetName() const
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBSymbol(%p)::GetName () => \"%s\"", m_opaque_ptr, name ? name : "");
+ log->Printf ("SBSymbol(%p)::GetName () => \"%s\"",
+ static_cast<void*>(m_opaque_ptr), name ? name : "");
return name;
}
@@ -79,7 +80,8 @@ SBSymbol::GetMangledName () const
name = m_opaque_ptr->GetMangled().GetMangledName().AsCString();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBSymbol(%p)::GetMangledName () => \"%s\"", m_opaque_ptr, name ? name : "");
+ log->Printf ("SBSymbol(%p)::GetMangledName () => \"%s\"",
+ static_cast<void*>(m_opaque_ptr), name ? name : "");
return name;
}
diff --git a/source/API/SBSymbolContext.cpp b/source/API/SBSymbolContext.cpp
index 479b0f75bfe9..481fa1a1d1a2 100644
--- a/source/API/SBSymbolContext.cpp
+++ b/source/API/SBSymbolContext.cpp
@@ -101,8 +101,9 @@ SBSymbolContext::GetModule ()
{
SBStream sstr;
sb_module.GetDescription (sstr);
- log->Printf ("SBSymbolContext(%p)::GetModule () => SBModule(%p): %s",
- m_opaque_ap.get(), module_sp.get(), sstr.GetData());
+ log->Printf ("SBSymbolContext(%p)::GetModule () => SBModule(%p): %s",
+ static_cast<void*>(m_opaque_ap.get()),
+ static_cast<void*>(module_sp.get()), sstr.GetData());
}
return sb_module;
@@ -120,15 +121,16 @@ SBSymbolContext::GetFunction ()
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
Function *function = NULL;
-
+
if (m_opaque_ap.get())
function = m_opaque_ap->function;
SBFunction sb_function (function);
if (log)
- log->Printf ("SBSymbolContext(%p)::GetFunction () => SBFunction(%p)",
- m_opaque_ap.get(), function);
+ log->Printf ("SBSymbolContext(%p)::GetFunction () => SBFunction(%p)",
+ static_cast<void*>(m_opaque_ap.get()),
+ static_cast<void*>(function));
return sb_function;
}
@@ -150,8 +152,9 @@ SBSymbolContext::GetLineEntry ()
if (log)
{
- log->Printf ("SBSymbolContext(%p)::GetLineEntry () => SBLineEntry(%p)",
- m_opaque_ap.get(), sb_line_entry.get());
+ log->Printf ("SBSymbolContext(%p)::GetLineEntry () => SBLineEntry(%p)",
+ static_cast<void*>(m_opaque_ap.get()),
+ static_cast<void*>(sb_line_entry.get()));
}
return sb_line_entry;
@@ -163,19 +166,18 @@ SBSymbolContext::GetSymbol ()
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
Symbol *symbol = NULL;
-
+
if (m_opaque_ap.get())
symbol = m_opaque_ap->symbol;
SBSymbol sb_symbol (symbol);
if (log)
- {
- log->Printf ("SBSymbolContext(%p)::GetSymbol () => SBSymbol(%p)",
- m_opaque_ap.get(), symbol);
- }
+ log->Printf ("SBSymbolContext(%p)::GetSymbol () => SBSymbol(%p)",
+ static_cast<void*>(m_opaque_ap.get()),
+ static_cast<void*>(symbol));
- return sb_symbol;
+ return sb_symbol;
}
void
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index 224349c0bce6..3d5828c5fe00 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -120,6 +120,18 @@ SBLaunchInfo::SetGroupID (uint32_t gid)
m_opaque_sp->SetGroupID (gid);
}
+SBFileSpec
+SBLaunchInfo::GetExecutableFile ()
+{
+ return SBFileSpec (m_opaque_sp->GetExecutableFile());
+}
+
+void
+SBLaunchInfo::SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg)
+{
+ m_opaque_sp->SetExecutableFile(exe_file.ref(), add_as_first_arg);
+}
+
uint32_t
SBLaunchInfo::GetNumArguments ()
{
@@ -268,6 +280,29 @@ SBLaunchInfo::AddSuppressFileAction (int fd, bool read, bool write)
return m_opaque_sp->AppendSuppressFileAction(fd, read, write);
}
+void
+SBLaunchInfo::SetLaunchEventData (const char *data)
+{
+ m_opaque_sp->SetLaunchEventData (data);
+}
+
+const char *
+SBLaunchInfo::GetLaunchEventData () const
+{
+ return m_opaque_sp->GetLaunchEventData ();
+}
+
+void
+SBLaunchInfo::SetDetachOnError (bool enable)
+{
+ m_opaque_sp->SetDetachOnError (enable);
+}
+
+bool
+SBLaunchInfo::GetDetachOnError () const
+{
+ return m_opaque_sp->GetDetachOnError ();
+}
SBAttachInfo::SBAttachInfo () :
m_opaque_sp (new ProcessAttachInfo())
@@ -541,10 +576,9 @@ SBTarget::GetProcess ()
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- {
- log->Printf ("SBTarget(%p)::GetProcess () => SBProcess(%p)",
- target_sp.get(), process_sp.get());
- }
+ log->Printf ("SBTarget(%p)::GetProcess () => SBProcess(%p)",
+ static_cast<void*>(target_sp.get()),
+ static_cast<void*>(process_sp.get()));
return sb_process;
}
@@ -641,19 +675,15 @@ SBTarget::Launch
TargetSP target_sp(GetSP());
if (log)
- {
log->Printf ("SBTarget(%p)::Launch (argv=%p, envp=%p, stdin=%s, stdout=%s, stderr=%s, working-dir=%s, launch_flags=0x%x, stop_at_entry=%i, &error (%p))...",
- target_sp.get(),
- argv,
- envp,
- stdin_path ? stdin_path : "NULL",
- stdout_path ? stdout_path : "NULL",
- stderr_path ? stderr_path : "NULL",
+ static_cast<void*>(target_sp.get()),
+ static_cast<void*>(argv), static_cast<void*>(envp),
+ stdin_path ? stdin_path : "NULL",
+ stdout_path ? stdout_path : "NULL",
+ stderr_path ? stderr_path : "NULL",
working_directory ? working_directory : "NULL",
- launch_flags,
- stop_at_entry,
- error.get());
- }
+ launch_flags, stop_at_entry,
+ static_cast<void*>(error.get()));
if (target_sp)
{
@@ -667,17 +697,17 @@ SBTarget::Launch
if (process_sp)
{
state = process_sp->GetState();
-
+
if (process_sp->IsAlive() && state != eStateConnected)
- {
+ {
if (state == eStateAttaching)
error.SetErrorString ("process attach is in progress");
else
error.SetErrorString ("a process is already being debugged");
return sb_process;
- }
+ }
}
-
+
if (state == eStateConnected)
{
// If we are already connected, then we have already specified the
@@ -694,7 +724,7 @@ SBTarget::Launch
launch_flags |= eLaunchFlagDisableSTDIO;
ProcessLaunchInfo launch_info (stdin_path, stdout_path, stderr_path, working_directory, launch_flags);
-
+
Module *exe_module = target_sp->GetExecutableModulePointer();
if (exe_module)
launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
@@ -717,10 +747,9 @@ SBTarget::Launch
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
if (log)
- {
- log->Printf ("SBTarget(%p)::Launch (...) => SBProcess(%p)",
- target_sp.get(), sb_process.GetSP().get());
- }
+ log->Printf ("SBTarget(%p)::Launch (...) => SBProcess(%p)",
+ static_cast<void*>(target_sp.get()),
+ static_cast<void*>(sb_process.GetSP().get()));
return sb_process;
}
@@ -729,46 +758,48 @@ SBProcess
SBTarget::Launch (SBLaunchInfo &sb_launch_info, SBError& error)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
SBProcess sb_process;
TargetSP target_sp(GetSP());
-
+
if (log)
- {
- log->Printf ("SBTarget(%p)::Launch (launch_info, error)...", target_sp.get());
- }
-
+ log->Printf ("SBTarget(%p)::Launch (launch_info, error)...",
+ static_cast<void*>(target_sp.get()));
+
if (target_sp)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
StateType state = eStateInvalid;
{
- ProcessSP process_sp = target_sp->GetProcessSP();
- if (process_sp)
- {
- state = process_sp->GetState();
-
- if (process_sp->IsAlive() && state != eStateConnected)
- {
- if (state == eStateAttaching)
- error.SetErrorString ("process attach is in progress");
- else
- error.SetErrorString ("a process is already being debugged");
- return sb_process;
- }
- }
+ ProcessSP process_sp = target_sp->GetProcessSP();
+ if (process_sp)
+ {
+ state = process_sp->GetState();
+
+ if (process_sp->IsAlive() && state != eStateConnected)
+ {
+ if (state == eStateAttaching)
+ error.SetErrorString ("process attach is in progress");
+ else
+ error.SetErrorString ("a process is already being debugged");
+ return sb_process;
+ }
+ }
}
lldb_private::ProcessLaunchInfo &launch_info = sb_launch_info.ref();
- Module *exe_module = target_sp->GetExecutableModulePointer();
- if (exe_module)
- launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
+ if (!launch_info.GetExecutableFile())
+ {
+ Module *exe_module = target_sp->GetExecutableModulePointer();
+ if (exe_module)
+ launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
+ }
const ArchSpec &arch_spec = target_sp->GetArchitecture();
if (arch_spec.IsValid())
launch_info.GetArchitecture () = arch_spec;
-
+
error.SetError (target_sp->Launch (target_sp->GetDebugger().GetListener(), launch_info));
sb_process.SetSP(target_sp->GetProcessSP());
}
@@ -776,14 +807,13 @@ SBTarget::Launch (SBLaunchInfo &sb_launch_info, SBError& error)
{
error.SetErrorString ("SBTarget is invalid");
}
-
+
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
if (log)
- {
log->Printf ("SBTarget(%p)::Launch (...) => SBProcess(%p)",
- target_sp.get(), sb_process.GetSP().get());
- }
-
+ static_cast<void*>(target_sp.get()),
+ static_cast<void*>(sb_process.GetSP().get()));
+
return sb_process;
}
@@ -791,41 +821,39 @@ lldb::SBProcess
SBTarget::Attach (SBAttachInfo &sb_attach_info, SBError& error)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
SBProcess sb_process;
ProcessSP process_sp;
TargetSP target_sp(GetSP());
-
+
if (log)
- {
- log->Printf ("SBTarget(%p)::Attach (sb_attach_info, error)...", target_sp.get());
- }
-
+ log->Printf ("SBTarget(%p)::Attach (sb_attach_info, error)...",
+ static_cast<void*>(target_sp.get()));
+
if (target_sp)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
-
+
StateType state = eStateInvalid;
process_sp = target_sp->GetProcessSP();
if (process_sp)
{
state = process_sp->GetState();
-
+
if (process_sp->IsAlive() && state != eStateConnected)
- {
+ {
if (state == eStateAttaching)
error.SetErrorString ("process attach is in progress");
else
error.SetErrorString ("a process is already being debugged");
if (log)
- {
log->Printf ("SBTarget(%p)::Attach (...) => error %s",
- target_sp.get(), error.GetCString());
- }
+ static_cast<void*>(target_sp.get()),
+ error.GetCString());
return sb_process;
- }
+ }
}
-
+
if (state != eStateConnected)
process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);
@@ -850,7 +878,7 @@ SBTarget::Attach (SBAttachInfo &sb_attach_info, SBError& error)
if (log)
{
log->Printf ("SBTarget(%p)::Attach (...) => error %s",
- target_sp.get(), error.GetCString());
+ static_cast<void*>(target_sp.get()), error.GetCString());
}
return sb_process;
}
@@ -875,13 +903,12 @@ SBTarget::Attach (SBAttachInfo &sb_attach_info, SBError& error)
{
error.SetErrorString ("SBTarget is invalid");
}
-
+
if (log)
- {
log->Printf ("SBTarget(%p)::Attach (...) => SBProcess(%p)",
- target_sp.get(), process_sp.get());
- }
-
+ static_cast<void*>(target_sp.get()),
+ static_cast<void*>(process_sp.get()));
+
return sb_process;
}
@@ -913,10 +940,9 @@ SBTarget::AttachToProcessWithID
TargetSP target_sp(GetSP());
if (log)
- {
- log->Printf ("SBTarget(%p)::AttachToProcessWithID (listener, pid=%" PRId64 ", error)...", target_sp.get(), pid);
- }
-
+ log->Printf ("SBTarget(%p)::AttachToProcessWithID (listener, pid=%" PRId64 ", error)...",
+ static_cast<void*>(target_sp.get()), pid);
+
if (target_sp)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
@@ -926,15 +952,15 @@ SBTarget::AttachToProcessWithID
if (process_sp)
{
state = process_sp->GetState();
-
+
if (process_sp->IsAlive() && state != eStateConnected)
- {
+ {
if (state == eStateAttaching)
error.SetErrorString ("process attach is in progress");
else
error.SetErrorString ("a process is already being debugged");
return sb_process;
- }
+ }
}
if (state == eStateConnected)
@@ -958,10 +984,10 @@ SBTarget::AttachToProcessWithID
if (process_sp)
{
sb_process.SetSP (process_sp);
-
+
ProcessAttachInfo attach_info;
attach_info.SetProcessID (pid);
-
+
PlatformSP platform_sp = target_sp->GetPlatform();
ProcessInstanceInfo instance_info;
if (platform_sp->GetProcessInfo(pid, instance_info))
@@ -986,12 +1012,11 @@ SBTarget::AttachToProcessWithID
{
error.SetErrorString ("SBTarget is invalid");
}
-
+
if (log)
- {
log->Printf ("SBTarget(%p)::AttachToProcessWithID (...) => SBProcess(%p)",
- target_sp.get(), process_sp.get());
- }
+ static_cast<void*>(target_sp.get()),
+ static_cast<void*>(process_sp.get()));
return sb_process;
}
@@ -1005,16 +1030,16 @@ SBTarget::AttachToProcessWithName
)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
SBProcess sb_process;
ProcessSP process_sp;
TargetSP target_sp(GetSP());
-
+
if (log)
- {
- log->Printf ("SBTarget(%p)::AttachToProcessWithName (listener, name=%s, wait_for=%s, error)...", target_sp.get(), name, wait_for ? "true" : "false");
- }
-
+ log->Printf ("SBTarget(%p)::AttachToProcessWithName (listener, name=%s, wait_for=%s, error)...",
+ static_cast<void*>(target_sp.get()), name,
+ wait_for ? "true" : "false");
+
if (name && target_sp)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
@@ -1024,17 +1049,17 @@ SBTarget::AttachToProcessWithName
if (process_sp)
{
state = process_sp->GetState();
-
+
if (process_sp->IsAlive() && state != eStateConnected)
- {
+ {
if (state == eStateAttaching)
error.SetErrorString ("process attach is in progress");
else
error.SetErrorString ("a process is already being debugged");
return sb_process;
- }
+ }
}
-
+
if (state == eStateConnected)
{
// If we are already connected, then we have already specified the
@@ -1078,12 +1103,11 @@ SBTarget::AttachToProcessWithName
{
error.SetErrorString ("SBTarget is invalid");
}
-
+
if (log)
- {
log->Printf ("SBTarget(%p)::AttachToPorcessWithName (...) => SBProcess(%p)",
- target_sp.get(), process_sp.get());
- }
+ static_cast<void*>(target_sp.get()),
+ static_cast<void*>(process_sp.get()));
return sb_process;
}
@@ -1101,12 +1125,11 @@ SBTarget::ConnectRemote
SBProcess sb_process;
ProcessSP process_sp;
TargetSP target_sp(GetSP());
-
+
if (log)
- {
- log->Printf ("SBTarget(%p)::ConnectRemote (listener, url=%s, plugin_name=%s, error)...", target_sp.get(), url, plugin_name);
- }
-
+ log->Printf ("SBTarget(%p)::ConnectRemote (listener, url=%s, plugin_name=%s, error)...",
+ static_cast<void*>(target_sp.get()), url, plugin_name);
+
if (target_sp)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
@@ -1114,8 +1137,7 @@ SBTarget::ConnectRemote
process_sp = target_sp->CreateProcess (listener.ref(), plugin_name, NULL);
else
process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), plugin_name, NULL);
-
-
+
if (process_sp)
{
sb_process.SetSP (process_sp);
@@ -1130,12 +1152,11 @@ SBTarget::ConnectRemote
{
error.SetErrorString ("SBTarget is invalid");
}
-
+
if (log)
- {
log->Printf ("SBTarget(%p)::ConnectRemote (...) => SBProcess(%p)",
- target_sp.get(), process_sp.get());
- }
+ static_cast<void*>(target_sp.get()),
+ static_cast<void*>(process_sp.get()));
return sb_process;
}
@@ -1155,8 +1176,9 @@ SBTarget::GetExecutable ()
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
{
- log->Printf ("SBTarget(%p)::GetExecutable () => SBFileSpec(%p)",
- target_sp.get(), exe_file_spec.get());
+ log->Printf ("SBTarget(%p)::GetExecutable () => SBFileSpec(%p)",
+ static_cast<void*>(target_sp.get()),
+ static_cast<const void*>(exe_file_spec.get()));
}
return exe_file_spec;
@@ -1258,7 +1280,7 @@ SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec,
if (target_sp && line != 0)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
-
+
const LazyBool check_inlines = eLazyBoolCalculate;
const LazyBool skip_prologue = eLazyBoolCalculate;
const bool internal = false;
@@ -1272,12 +1294,9 @@ SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec,
sb_bp.GetDescription (sstr);
char path[PATH_MAX];
sb_file_spec->GetPath (path, sizeof(path));
- log->Printf ("SBTarget(%p)::BreakpointCreateByLocation ( %s:%u ) => SBBreakpoint(%p): %s",
- target_sp.get(),
- path,
- line,
- sb_bp.get(),
- sstr.GetData());
+ log->Printf ("SBTarget(%p)::BreakpointCreateByLocation ( %s:%u ) => SBBreakpoint(%p): %s",
+ static_cast<void*>(target_sp.get()), path, line,
+ static_cast<void*>(sb_bp.get()), sstr.GetData());
}
return sb_bp;
@@ -1294,7 +1313,7 @@ SBTarget::BreakpointCreateByName (const char *symbol_name,
if (target_sp.get())
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
-
+
const bool internal = false;
const bool hardware = false;
const LazyBool skip_prologue = eLazyBoolCalculate;
@@ -1309,12 +1328,11 @@ SBTarget::BreakpointCreateByName (const char *symbol_name,
*sb_bp = target_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal, hardware);
}
}
-
+
if (log)
- {
- log->Printf ("SBTarget(%p)::BreakpointCreateByName (symbol=\"%s\", module=\"%s\") => SBBreakpoint(%p)",
- target_sp.get(), symbol_name, module_name, sb_bp.get());
- }
+ log->Printf ("SBTarget(%p)::BreakpointCreateByName (symbol=\"%s\", module=\"%s\") => SBBreakpoint(%p)",
+ static_cast<void*>(target_sp.get()), symbol_name,
+ module_name, static_cast<void*>(sb_bp.get()));
return sb_bp;
}
@@ -1352,12 +1370,11 @@ SBTarget::BreakpointCreateByName (const char *symbol_name,
internal,
hardware);
}
-
+
if (log)
- {
- log->Printf ("SBTarget(%p)::BreakpointCreateByName (symbol=\"%s\", name_type: %d) => SBBreakpoint(%p)",
- target_sp.get(), symbol_name, name_type_mask, sb_bp.get());
- }
+ log->Printf ("SBTarget(%p)::BreakpointCreateByName (symbol=\"%s\", name_type: %d) => SBBreakpoint(%p)",
+ static_cast<void*>(target_sp.get()), symbol_name,
+ name_type_mask, static_cast<void*>(sb_bp.get()));
return sb_bp;
}
@@ -1388,10 +1405,11 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[],
internal,
hardware);
}
-
+
if (log)
{
- log->Printf ("SBTarget(%p)::BreakpointCreateByName (symbols={", target_sp.get());
+ log->Printf ("SBTarget(%p)::BreakpointCreateByName (symbols={",
+ static_cast<void*>(target_sp.get()));
for (uint32_t i = 0 ; i < num_names; i++)
{
char sep;
@@ -1403,9 +1421,9 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[],
log->Printf ("\"%s\"%c ", symbol_names[i], sep);
else
log->Printf ("\"<NULL>\"%c ", sep);
-
}
- log->Printf ("name_type: %d) => SBBreakpoint(%p)", name_type_mask, sb_bp.get());
+ log->Printf ("name_type: %d) => SBBreakpoint(%p)", name_type_mask,
+ static_cast<void*>(sb_bp.get()));
}
return sb_bp;
@@ -1426,12 +1444,12 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
const bool internal = false;
const bool hardware = false;
const LazyBool skip_prologue = eLazyBoolCalculate;
-
+
if (module_name && module_name[0])
{
FileSpecList module_spec_list;
module_spec_list.Append (FileSpec (module_name, false));
-
+
*sb_bp = target_sp->CreateFuncRegexBreakpoint (&module_spec_list, NULL, regexp, skip_prologue, internal, hardware);
}
else
@@ -1441,10 +1459,9 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
}
if (log)
- {
- log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\", module_name=\"%s\") => SBBreakpoint(%p)",
- target_sp.get(), symbol_name_regex, module_name, sb_bp.get());
- }
+ log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\", module_name=\"%s\") => SBBreakpoint(%p)",
+ static_cast<void*>(target_sp.get()), symbol_name_regex,
+ module_name, static_cast<void*>(sb_bp.get()));
return sb_bp;
}
@@ -1465,15 +1482,14 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
const bool internal = false;
const bool hardware = false;
const LazyBool skip_prologue = eLazyBoolCalculate;
-
+
*sb_bp = target_sp->CreateFuncRegexBreakpoint (module_list.get(), comp_unit_list.get(), regexp, skip_prologue, internal, hardware);
}
if (log)
- {
- log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\") => SBBreakpoint(%p)",
- target_sp.get(), symbol_name_regex, sb_bp.get());
- }
+ log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\") => SBBreakpoint(%p)",
+ static_cast<void*>(target_sp.get()), symbol_name_regex,
+ static_cast<void*>(sb_bp.get()));
return sb_bp;
}
@@ -1491,11 +1507,12 @@ SBTarget::BreakpointCreateByAddress (addr_t address)
const bool hardware = false;
*sb_bp = target_sp->CreateBreakpoint (address, false, hardware);
}
-
+
if (log)
- {
- log->Printf ("SBTarget(%p)::BreakpointCreateByAddress (address=%" PRIu64 ") => SBBreakpoint(%p)", target_sp.get(), (uint64_t) address, sb_bp.get());
- }
+ log->Printf ("SBTarget(%p)::BreakpointCreateByAddress (address=%" PRIu64 ") => SBBreakpoint(%p)",
+ static_cast<void*>(target_sp.get()),
+ static_cast<uint64_t>(address),
+ static_cast<void*>(sb_bp.get()));
return sb_bp;
}
@@ -1516,12 +1533,12 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex,
FileSpecList source_file_spec_list;
const bool hardware = false;
source_file_spec_list.Append (source_file.ref());
-
+
if (module_name && module_name[0])
{
FileSpecList module_spec_list;
module_spec_list.Append (FileSpec (module_name, false));
-
+
*sb_bp = target_sp->CreateSourceRegexBreakpoint (&module_spec_list, &source_file_spec_list, regexp, false, hardware);
}
else
@@ -1534,8 +1551,9 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex,
{
char path[PATH_MAX];
source_file->GetPath (path, sizeof(path));
- log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (source_regex=\"%s\", file=\"%s\", module_name=\"%s\") => SBBreakpoint(%p)",
- target_sp.get(), source_regex, path, module_name, sb_bp.get());
+ log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (source_regex=\"%s\", file=\"%s\", module_name=\"%s\") => SBBreakpoint(%p)",
+ static_cast<void*>(target_sp.get()), source_regex, path,
+ module_name, static_cast<void*>(sb_bp.get()));
}
return sb_bp;
@@ -1559,10 +1577,9 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex,
}
if (log)
- {
- log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (source_regex=\"%s\") => SBBreakpoint(%p)",
- target_sp.get(), source_regex, sb_bp.get());
- }
+ log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (source_regex=\"%s\") => SBBreakpoint(%p)",
+ static_cast<void*>(target_sp.get()), source_regex,
+ static_cast<void*>(sb_bp.get()));
return sb_bp;
}
@@ -1584,14 +1601,11 @@ SBTarget::BreakpointCreateForException (lldb::LanguageType language,
}
if (log)
- {
- log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (Language: %s, catch: %s throw: %s) => SBBreakpoint(%p)",
- target_sp.get(),
+ log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (Language: %s, catch: %s throw: %s) => SBBreakpoint(%p)",
+ static_cast<void*>(target_sp.get()),
LanguageRuntime::GetNameForLanguageType(language),
- catch_bp ? "on" : "off",
- throw_bp ? "on" : "off",
- sb_bp.get());
- }
+ catch_bp ? "on" : "off", throw_bp ? "on" : "off",
+ static_cast<void*>(sb_bp.get()));
return sb_bp;
}
@@ -1635,9 +1649,9 @@ SBTarget::BreakpointDelete (break_id_t bp_id)
}
if (log)
- {
- log->Printf ("SBTarget(%p)::BreakpointDelete (bp_id=%d) => %i", target_sp.get(), (uint32_t) bp_id, result);
- }
+ log->Printf ("SBTarget(%p)::BreakpointDelete (bp_id=%d) => %i",
+ static_cast<void*>(target_sp.get()),
+ static_cast<uint32_t>(bp_id), result);
return result;
}
@@ -1656,10 +1670,10 @@ SBTarget::FindBreakpointByID (break_id_t bp_id)
}
if (log)
- {
- log->Printf ("SBTarget(%p)::FindBreakpointByID (bp_id=%d) => SBBreakpoint(%p)",
- target_sp.get(), (uint32_t) bp_id, sb_breakpoint.get());
- }
+ log->Printf ("SBTarget(%p)::FindBreakpointByID (bp_id=%d) => SBBreakpoint(%p)",
+ static_cast<void*>(target_sp.get()),
+ static_cast<uint32_t>(bp_id),
+ static_cast<void*>(sb_breakpoint.get()));
return sb_breakpoint;
}
@@ -1744,9 +1758,9 @@ SBTarget::DeleteWatchpoint (watch_id_t wp_id)
}
if (log)
- {
- log->Printf ("SBTarget(%p)::WatchpointDelete (wp_id=%d) => %i", target_sp.get(), (uint32_t) wp_id, result);
- }
+ log->Printf ("SBTarget(%p)::WatchpointDelete (wp_id=%d) => %i",
+ static_cast<void*>(target_sp.get()),
+ static_cast<uint32_t>(wp_id), result);
return result;
}
@@ -1769,10 +1783,10 @@ SBTarget::FindWatchpointByID (lldb::watch_id_t wp_id)
}
if (log)
- {
- log->Printf ("SBTarget(%p)::FindWatchpointByID (bp_id=%d) => SBWatchpoint(%p)",
- target_sp.get(), (uint32_t) wp_id, watchpoint_sp.get());
- }
+ log->Printf ("SBTarget(%p)::FindWatchpointByID (bp_id=%d) => SBWatchpoint(%p)",
+ static_cast<void*>(target_sp.get()),
+ static_cast<uint32_t>(wp_id),
+ static_cast<void*>(watchpoint_sp.get()));
return sb_watchpoint;
}
@@ -1781,7 +1795,7 @@ lldb::SBWatchpoint
SBTarget::WatchAddress (lldb::addr_t addr, size_t size, bool read, bool write, SBError &error)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
SBWatchpoint sb_watchpoint;
lldb::WatchpointSP watchpoint_sp;
TargetSP target_sp(GetSP());
@@ -1798,7 +1812,7 @@ SBTarget::WatchAddress (lldb::addr_t addr, size_t size, bool read, bool write, S
error.SetErrorString("Can't create a watchpoint that is neither read nor write.");
return sb_watchpoint;
}
-
+
// Target::CreateWatchpoint() is thread safe.
Error cw_error;
// This API doesn't take in a type, so we can't figure out what it is.
@@ -1807,13 +1821,13 @@ SBTarget::WatchAddress (lldb::addr_t addr, size_t size, bool read, bool write, S
error.SetError(cw_error);
sb_watchpoint.SetSP (watchpoint_sp);
}
-
+
if (log)
- {
log->Printf ("SBTarget(%p)::WatchAddress (addr=0x%" PRIx64 ", 0x%u) => SBWatchpoint(%p)",
- target_sp.get(), addr, (uint32_t) size, watchpoint_sp.get());
- }
-
+ static_cast<void*>(target_sp.get()), addr,
+ static_cast<uint32_t>(size),
+ static_cast<void*>(watchpoint_sp.get()));
+
return sb_watchpoint;
}
@@ -1860,7 +1874,7 @@ SBTarget::CreateValueFromAddress (const char *name, SBAddress addr, SBType type)
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,
@@ -1868,7 +1882,7 @@ SBTarget::CreateValueFromAddress (const char *name, SBAddress addr, SBType type)
buffer,
exe_ctx.GetByteOrder(),
exe_ctx.GetAddressByteSize()));
-
+
if (ptr_result_valobj_sp)
{
ptr_result_valobj_sp->GetValue().SetValueType(Value::eValueTypeLoadAddress);
@@ -1884,9 +1898,12 @@ SBTarget::CreateValueFromAddress (const char *name, SBAddress addr, SBType type)
if (log)
{
if (new_value_sp)
- log->Printf ("SBTarget(%p)::CreateValueFromAddress => \"%s\"", m_opaque_sp.get(), new_value_sp->GetName().AsCString());
+ log->Printf ("SBTarget(%p)::CreateValueFromAddress => \"%s\"",
+ static_cast<void*>(m_opaque_sp.get()),
+ new_value_sp->GetName().AsCString());
else
- log->Printf ("SBTarget(%p)::CreateValueFromAddress => NULL", m_opaque_sp.get());
+ log->Printf ("SBTarget(%p)::CreateValueFromAddress => NULL",
+ static_cast<void*>(m_opaque_sp.get()));
}
return sb_value;
}
@@ -1981,7 +1998,8 @@ SBTarget::GetNumModules () const
}
if (log)
- log->Printf ("SBTarget(%p)::GetNumModules () => %d", target_sp.get(), num);
+ log->Printf ("SBTarget(%p)::GetNumModules () => %d",
+ static_cast<void*>(target_sp.get()), num);
return num;
}
@@ -1992,7 +2010,8 @@ SBTarget::Clear ()
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBTarget(%p)::Clear ()", m_opaque_sp.get());
+ log->Printf ("SBTarget(%p)::Clear ()",
+ static_cast<void*>(m_opaque_sp.get()));
m_opaque_sp.reset();
}
@@ -2063,10 +2082,9 @@ SBTarget::GetModuleAtIndex (uint32_t idx)
}
if (log)
- {
- log->Printf ("SBTarget(%p)::GetModuleAtIndex (idx=%d) => SBModule(%p)",
- target_sp.get(), idx, module_sp.get());
- }
+ log->Printf ("SBTarget(%p)::GetModuleAtIndex (idx=%d) => SBModule(%p)",
+ static_cast<void*>(target_sp.get()), idx,
+ static_cast<void*>(module_sp.get()));
return sb_module;
}
@@ -2088,10 +2106,11 @@ SBTarget::GetBroadcaster () const
TargetSP target_sp(GetSP());
SBBroadcaster broadcaster(target_sp.get(), false);
-
+
if (log)
- log->Printf ("SBTarget(%p)::GetBroadcaster () => SBBroadcaster(%p)",
- target_sp.get(), broadcaster.get());
+ log->Printf ("SBTarget(%p)::GetBroadcaster () => SBBroadcaster(%p)",
+ static_cast<void*>(target_sp.get()),
+ static_cast<void*>(broadcaster.get()));
return broadcaster;
}
@@ -2432,10 +2451,6 @@ SBTarget::SetSectionLoadAddress (lldb::SBSection section,
else
{
ProcessSP process_sp (target_sp->GetProcessSP());
- uint32_t stop_id = 0;
- if (process_sp)
- stop_id = process_sp->GetStopID();
-
if (target_sp->SetSectionLoadAddress (section_sp, section_base_addr))
{
// Flush info in the process (stack frames, etc)
@@ -2468,10 +2483,6 @@ SBTarget::ClearSectionLoadAddress (lldb::SBSection section)
else
{
ProcessSP process_sp (target_sp->GetProcessSP());
- uint32_t stop_id = 0;
- if (process_sp)
- stop_id = process_sp->GetStopID();
-
if (target_sp->SetSectionUnloaded (section.GetSP()))
{
// Flush info in the process (stack frames, etc)
@@ -2547,9 +2558,6 @@ SBTarget::ClearModuleLoadAddress (lldb::SBModule module)
if (section_list)
{
ProcessSP process_sp (target_sp->GetProcessSP());
- uint32_t stop_id = 0;
- if (process_sp)
- stop_id = process_sp->GetStopID();
bool changed = false;
const size_t num_sections = section_list->GetSize();
@@ -2557,7 +2565,7 @@ SBTarget::ClearModuleLoadAddress (lldb::SBModule module)
{
SectionSP section_sp (section_list->GetSectionAtIndex(sect_idx));
if (section_sp)
- changed |= target_sp->SetSectionUnloaded (section_sp) > 0;
+ changed |= target_sp->SetSectionUnloaded (section_sp);
}
if (changed)
{
@@ -2619,7 +2627,7 @@ SBTarget::EvaluateExpression (const char *expr, const SBExpressionOptions &optio
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
Log * expr_log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
SBValue expr_result;
- ExecutionResults exe_results = eExecutionSetupError;
+ ExpressionResults exe_results = eExpressionSetupError;
ValueObjectSP expr_value_sp;
TargetSP target_sp(GetSP());
StackFrame *frame = NULL;
@@ -2631,16 +2639,16 @@ SBTarget::EvaluateExpression (const char *expr, const SBExpressionOptions &optio
log->Printf ("SBTarget::EvaluateExpression called with an empty expression");
return expr_result;
}
-
+
Mutex::Locker api_locker (target_sp->GetAPIMutex());
ExecutionContext exe_ctx (m_opaque_sp.get());
-
+
if (log)
log->Printf ("SBTarget()::EvaluateExpression (expr=\"%s\")...", expr);
-
+
frame = exe_ctx.GetFramePtr();
Target *target = exe_ctx.GetTargetPtr();
-
+
if (target)
{
#ifdef LLDB_CONFIGURATION_DEBUG
@@ -2669,17 +2677,14 @@ SBTarget::EvaluateExpression (const char *expr, const SBExpressionOptions &optio
#ifndef LLDB_DISABLE_PYTHON
if (expr_log)
expr_log->Printf("** [SBTarget::EvaluateExpression] Expression result is %s, summary %s **",
- expr_result.GetValue(),
- expr_result.GetSummary());
-
+ expr_result.GetValue(), expr_result.GetSummary());
+
if (log)
log->Printf ("SBTarget(%p)::EvaluateExpression (expr=\"%s\") => SBValue(%p) (execution result=%d)",
- frame,
- expr,
- expr_value_sp.get(),
- exe_results);
+ static_cast<void*>(frame), expr,
+ static_cast<void*>(expr_value_sp.get()), exe_results);
#endif
-
+
return expr_result;
}
diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp
index 4170d5b230bb..a0bfa4313535 100644
--- a/source/API/SBThread.cpp
+++ b/source/API/SBThread.cpp
@@ -19,10 +19,12 @@
#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/Process.h"
+#include "lldb/Target/Queue.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Target/StopInfo.h"
@@ -88,6 +90,42 @@ SBThread::~SBThread()
{
}
+lldb::SBQueue
+SBThread::GetQueue () const
+{
+ SBQueue sb_queue;
+ QueueSP queue_sp;
+ Mutex::Locker api_locker;
+ ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (exe_ctx.HasThreadScope())
+ {
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
+ {
+ queue_sp = exe_ctx.GetThreadPtr()->GetQueue();
+ if (queue_sp)
+ {
+ sb_queue.SetQueue (queue_sp);
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("SBThread(%p)::GetQueueKind() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
+ }
+ }
+
+ if (log)
+ log->Printf ("SBThread(%p)::GetQueueKind () => SBQueue(%p)",
+ static_cast<void*>(exe_ctx.GetThreadPtr()), static_cast<void*>(queue_sp.get()));
+
+ return sb_queue;
+}
+
+
bool
SBThread::IsValid() const
{
@@ -120,12 +158,14 @@ SBThread::GetStopReason()
else
{
if (log)
- log->Printf ("SBThread(%p)::GetStopReason() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetStopReason() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
if (log)
- log->Printf ("SBThread(%p)::GetStopReason () => %s", exe_ctx.GetThreadPtr(),
+ log->Printf ("SBThread(%p)::GetStopReason () => %s",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
Thread::StopReasonAsCString (reason));
return reason;
@@ -183,7 +223,8 @@ SBThread::GetStopReasonDataCount ()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBThread(%p)::GetStopReasonDataCount() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetStopReasonDataCount() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
return 0;
@@ -226,7 +267,7 @@ SBThread::GetStopReasonDataAtIndex (uint32_t idx)
BreakpointLocationSP bp_loc_sp (bp_site_sp->GetOwnerAtIndex (bp_index));
if (bp_loc_sp)
{
- if (bp_index & 1)
+ if (idx & 1)
{
// Odd idx, return the breakpoint location ID
return bp_loc_sp->GetID();
@@ -257,7 +298,8 @@ SBThread::GetStopReasonDataAtIndex (uint32_t idx)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBThread(%p)::GetStopReasonDataAtIndex() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetStopReasonDataAtIndex() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
return 0;
@@ -284,8 +326,9 @@ SBThread::GetStopDescription (char *dst, size_t dst_len)
if (stop_desc)
{
if (log)
- log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => \"%s\"",
- exe_ctx.GetThreadPtr(), stop_desc);
+ log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => \"%s\"",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ stop_desc);
if (dst)
return ::snprintf (dst, dst_len, "%s", stop_desc);
else
@@ -362,19 +405,20 @@ SBThread::GetStopDescription (char *dst, size_t dst_len)
default:
break;
}
-
+
if (stop_desc && stop_desc[0])
{
if (log)
- log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => '%s'",
- exe_ctx.GetThreadPtr(), stop_desc);
+ log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => '%s'",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ stop_desc);
if (dst)
return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte
if (stop_desc_len == 0)
stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte
-
+
return stop_desc_len;
}
}
@@ -384,7 +428,8 @@ SBThread::GetStopDescription (char *dst, size_t dst_len)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBThread(%p)::GetStopDescription() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetStopDescription() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
if (dst)
@@ -414,16 +459,18 @@ SBThread::GetStopReturnValue ()
else
{
if (log)
- log->Printf ("SBThread(%p)::GetStopReturnValue() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetStopReturnValue() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
-
+
if (log)
- log->Printf ("SBThread(%p)::GetStopReturnValue () => %s", exe_ctx.GetThreadPtr(),
- return_valobj_sp.get()
- ? return_valobj_sp->GetValueAsCString()
- : "<no return value>");
-
+ log->Printf ("SBThread(%p)::GetStopReturnValue () => %s",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ return_valobj_sp.get()
+ ? return_valobj_sp->GetValueAsCString()
+ : "<no return value>");
+
return SBValue (return_valobj_sp);
}
@@ -469,12 +516,15 @@ SBThread::GetName () const
else
{
if (log)
- log->Printf ("SBThread(%p)::GetName() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetName() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
-
+
if (log)
- log->Printf ("SBThread(%p)::GetName () => %s", exe_ctx.GetThreadPtr(), name ? name : "NULL");
+ log->Printf ("SBThread(%p)::GetName () => %s",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ name ? name : "NULL");
return name;
}
@@ -497,12 +547,15 @@ SBThread::GetQueueName () const
else
{
if (log)
- log->Printf ("SBThread(%p)::GetQueueName() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetQueueName() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
-
+
if (log)
- log->Printf ("SBThread(%p)::GetQueueName () => %s", exe_ctx.GetThreadPtr(), name ? name : "NULL");
+ log->Printf ("SBThread(%p)::GetQueueName () => %s",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ name ? name : "NULL");
return name;
}
@@ -525,16 +578,86 @@ SBThread::GetQueueID () const
else
{
if (log)
- log->Printf ("SBThread(%p)::GetQueueID() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetQueueID() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
-
+
if (log)
- log->Printf ("SBThread(%p)::GetQueueID () => 0x%" PRIx64, exe_ctx.GetThreadPtr(), id);
+ log->Printf ("SBThread(%p)::GetQueueID () => 0x%" PRIx64,
+ static_cast<void*>(exe_ctx.GetThreadPtr()), id);
return id;
}
+bool
+SBThread::GetInfoItemByPathAsString (const char *path, SBStream &strm)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ bool success = false;
+ Mutex::Locker api_locker;
+ ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
+
+ if (exe_ctx.HasThreadScope())
+ {
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
+ {
+ Thread *thread = exe_ctx.GetThreadPtr();
+ StructuredData::ObjectSP info_root_sp = thread->GetExtendedInfo();
+ if (info_root_sp)
+ {
+ StructuredData::ObjectSP node = info_root_sp->GetObjectForDotSeparatedPath (path);
+ if (node)
+ {
+ if (node->GetType() == StructuredData::Type::eTypeString)
+ {
+ strm.Printf ("%s", node->GetAsString()->GetValue().c_str());
+ success = true;
+ }
+ if (node->GetType() == StructuredData::Type::eTypeInteger)
+ {
+ strm.Printf ("0x%" PRIx64, node->GetAsInteger()->GetValue());
+ success = true;
+ }
+ if (node->GetType() == StructuredData::Type::eTypeFloat)
+ {
+ strm.Printf ("0x%f", node->GetAsFloat()->GetValue());
+ success = true;
+ }
+ if (node->GetType() == StructuredData::Type::eTypeBoolean)
+ {
+ if (node->GetAsBoolean()->GetValue() == true)
+ strm.Printf ("true");
+ else
+ strm.Printf ("false");
+ success = true;
+ }
+ if (node->GetType() == StructuredData::Type::eTypeNull)
+ {
+ strm.Printf ("null");
+ success = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("SBThread(%p)::GetInfoItemByPathAsString() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
+ }
+ }
+
+ if (log)
+ log->Printf ("SBThread(%p)::GetInfoItemByPathAsString () => %s",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ strm.GetData());
+
+ return success;
+}
+
+
SBError
SBThread::ResumeNewPlan (ExecutionContext &exe_ctx, ThreadPlan *new_plan)
{
@@ -587,9 +710,10 @@ SBThread::StepOver (lldb::RunMode stop_other_threads)
if (log)
- log->Printf ("SBThread(%p)::StepOver (stop_other_threads='%s')", exe_ctx.GetThreadPtr(),
+ log->Printf ("SBThread(%p)::StepOver (stop_other_threads='%s')",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
Thread::RunModeAsCString (stop_other_threads));
-
+
if (exe_ctx.HasThreadScope())
{
Thread *thread = exe_ctx.GetThreadPtr();
@@ -601,17 +725,19 @@ SBThread::StepOver (lldb::RunMode stop_other_threads)
{
if (frame_sp->HasDebugInformation ())
{
+ const LazyBool avoid_no_debug = eLazyBoolCalculate;
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
sc.line_entry.range,
sc,
- stop_other_threads);
+ stop_other_threads,
+ avoid_no_debug);
}
else
{
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true,
- abort_other_plans,
- stop_other_threads);
+ abort_other_plans,
+ stop_other_threads);
}
}
@@ -636,10 +762,10 @@ SBThread::StepInto (const char *target_name, lldb::RunMode stop_other_threads)
if (log)
log->Printf ("SBThread(%p)::StepInto (target_name='%s', stop_other_threads='%s')",
- exe_ctx.GetThreadPtr(),
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
target_name? target_name: "<NULL>",
Thread::RunModeAsCString (stop_other_threads));
-
+
if (exe_ctx.HasThreadScope())
{
bool abort_other_plans = false;
@@ -650,22 +776,24 @@ SBThread::StepInto (const char *target_name, lldb::RunMode stop_other_threads)
if (frame_sp && frame_sp->HasDebugInformation ())
{
- bool avoid_code_without_debug_info = true;
+ const LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate;
+ const LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate;
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
sc.line_entry.range,
sc,
target_name,
stop_other_threads,
- avoid_code_without_debug_info);
+ step_in_avoids_code_without_debug_info,
+ step_out_avoids_code_without_debug_info);
}
else
{
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false,
- abort_other_plans,
- stop_other_threads);
+ abort_other_plans,
+ stop_other_threads);
}
-
+
// This returns an error, we should use it!
ResumeNewPlan (exe_ctx, new_plan_sp.get());
}
@@ -681,8 +809,9 @@ SBThread::StepOut ()
if (log)
- log->Printf ("SBThread(%p)::StepOut ()", exe_ctx.GetThreadPtr());
-
+ log->Printf ("SBThread(%p)::StepOut ()",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
+
if (exe_ctx.HasThreadScope())
{
bool abort_other_plans = false;
@@ -690,14 +819,16 @@ SBThread::StepOut ()
Thread *thread = exe_ctx.GetThreadPtr();
+ const LazyBool avoid_no_debug = eLazyBoolCalculate;
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut (abort_other_plans,
- NULL,
- false,
- stop_other_threads,
- eVoteYes,
- eVoteNoOpinion,
- 0));
-
+ NULL,
+ false,
+ stop_other_threads,
+ eVoteYes,
+ eVoteNoOpinion,
+ 0,
+ avoid_no_debug));
+
// This returns an error, we should use it!
ResumeNewPlan (exe_ctx, new_plan_sp.get());
}
@@ -716,7 +847,10 @@ SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame)
{
SBStream frame_desc_strm;
sb_frame.GetDescription (frame_desc_strm);
- log->Printf ("SBThread(%p)::StepOutOfFrame (frame = SBFrame(%p): %s)", exe_ctx.GetThreadPtr(), frame_sp.get(), frame_desc_strm.GetData());
+ log->Printf ("SBThread(%p)::StepOutOfFrame (frame = SBFrame(%p): %s)",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ static_cast<void*>(frame_sp.get()),
+ frame_desc_strm.GetData());
}
if (exe_ctx.HasThreadScope())
@@ -726,13 +860,13 @@ SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame)
Thread *thread = exe_ctx.GetThreadPtr();
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut (abort_other_plans,
- NULL,
- false,
- stop_other_threads,
- eVoteYes,
+ NULL,
+ false,
+ stop_other_threads,
+ eVoteYes,
eVoteNoOpinion,
frame_sp->GetFrameIndex()));
-
+
// This returns an error, we should use it!
ResumeNewPlan (exe_ctx, new_plan_sp.get());
}
@@ -749,13 +883,14 @@ SBThread::StepInstruction (bool step_over)
if (log)
- log->Printf ("SBThread(%p)::StepInstruction (step_over=%i)", exe_ctx.GetThreadPtr(), step_over);
-
+ log->Printf ("SBThread(%p)::StepInstruction (step_over=%i)",
+ static_cast<void*>(exe_ctx.GetThreadPtr()), step_over);
+
if (exe_ctx.HasThreadScope())
{
Thread *thread = exe_ctx.GetThreadPtr();
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepSingleInstruction (step_over, true, true));
-
+
// This returns an error, we should use it!
ResumeNewPlan (exe_ctx, new_plan_sp.get());
}
@@ -771,8 +906,9 @@ SBThread::RunToAddress (lldb::addr_t addr)
if (log)
- log->Printf ("SBThread(%p)::RunToAddress (addr=0x%" PRIx64 ")", exe_ctx.GetThreadPtr(), addr);
-
+ log->Printf ("SBThread(%p)::RunToAddress (addr=0x%" PRIx64 ")",
+ static_cast<void*>(exe_ctx.GetThreadPtr()), addr);
+
if (exe_ctx.HasThreadScope())
{
bool abort_other_plans = false;
@@ -783,7 +919,7 @@ 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));
-
+
// This returns an error, we should use it!
ResumeNewPlan (exe_ctx, new_plan_sp.get());
}
@@ -797,7 +933,7 @@ SBThread::StepOverUntil (lldb::SBFrame &sb_frame,
SBError sb_error;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
char path[PATH_MAX];
-
+
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
@@ -808,11 +944,10 @@ SBThread::StepOverUntil (lldb::SBFrame &sb_frame,
SBStream frame_desc_strm;
sb_frame.GetDescription (frame_desc_strm);
sb_file_spec->GetPath (path, sizeof(path));
- log->Printf ("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, file+line = %s:%u)",
- exe_ctx.GetThreadPtr(),
- frame_sp.get(),
- frame_desc_strm.GetData(),
- path, line);
+ log->Printf ("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, file+line = %s:%u)",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ static_cast<void*>(frame_sp.get()),
+ frame_desc_strm.GetData(), path, line);
}
if (exe_ctx.HasThreadScope())
@@ -825,14 +960,14 @@ SBThread::StepOverUntil (lldb::SBFrame &sb_frame,
sb_error.SetErrorString("invalid line argument");
return sb_error;
}
-
+
if (!frame_sp)
{
frame_sp = thread->GetSelectedFrame ();
if (!frame_sp)
frame_sp = thread->GetStackFrameAtIndex (0);
}
-
+
SymbolContext frame_sc;
if (!frame_sp)
{
@@ -845,13 +980,13 @@ SBThread::StepOverUntil (lldb::SBFrame &sb_frame,
eSymbolContextFunction |
eSymbolContextLineEntry |
eSymbolContextSymbol );
-
+
if (frame_sc.comp_unit == NULL)
{
sb_error.SetErrorStringWithFormat("frame %u doesn't have debug information", frame_sp->GetFrameIndex());
return sb_error;
}
-
+
FileSpec step_file_spec;
if (sb_file_spec.IsValid())
{
@@ -868,15 +1003,15 @@ SBThread::StepOverUntil (lldb::SBFrame &sb_frame,
return sb_error;
}
}
-
+
// Grab the current function, then we will make sure the "until" address is
// within the function. We discard addresses that are out of the current
// function, and then if there are no addresses remaining, give an appropriate
// error message.
-
+
bool all_in_function = true;
AddressRange fun_range = frame_sc.function->GetAddressRange();
-
+
std::vector<addr_t> step_over_until_addrs;
const bool abort_other_plans = false;
const bool stop_other_threads = false;
@@ -908,7 +1043,7 @@ SBThread::StepOverUntil (lldb::SBFrame &sb_frame,
}
}
}
-
+
if (step_over_until_addrs.empty())
{
if (all_in_function)
@@ -947,7 +1082,9 @@ SBThread::JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line)
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
if (log)
- log->Printf ("SBThread(%p)::JumpToLine (file+line = %s:%u)", exe_ctx.GetThreadPtr(), file_spec->GetPath().c_str(), line);
+ log->Printf ("SBThread(%p)::JumpToLine (file+line = %s:%u)",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ file_spec->GetPath().c_str(), line);
if (!exe_ctx.HasThreadScope())
{
@@ -966,7 +1103,7 @@ SBError
SBThread::ReturnFromFrame (SBFrame &frame, SBValue &return_value)
{
SBError sb_error;
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
Mutex::Locker api_locker;
@@ -974,14 +1111,16 @@ SBThread::ReturnFromFrame (SBFrame &frame, SBValue &return_value)
if (log)
- log->Printf ("SBThread(%p)::ReturnFromFrame (frame=%d)", exe_ctx.GetThreadPtr(), frame.GetFrameID());
-
+ log->Printf ("SBThread(%p)::ReturnFromFrame (frame=%d)",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ frame.GetFrameID());
+
if (exe_ctx.HasThreadScope())
{
Thread *thread = exe_ctx.GetThreadPtr();
sb_error.SetError (thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
}
-
+
return sb_error;
}
@@ -1003,11 +1142,13 @@ SBThread::Suspend()
else
{
if (log)
- log->Printf ("SBThread(%p)::Suspend() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::Suspend() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
if (log)
- log->Printf ("SBThread(%p)::Suspend() => %i", exe_ctx.GetThreadPtr(), result);
+ log->Printf ("SBThread(%p)::Suspend() => %i",
+ static_cast<void*>(exe_ctx.GetThreadPtr()), result);
return result;
}
@@ -1022,17 +1163,20 @@ SBThread::Resume ()
Process::StopLocker stop_locker;
if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
{
- exe_ctx.GetThreadPtr()->SetResumeState (eStateRunning);
+ const bool override_suspend = true;
+ exe_ctx.GetThreadPtr()->SetResumeState (eStateRunning, override_suspend);
result = true;
}
else
{
if (log)
- log->Printf ("SBThread(%p)::Resume() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::Resume() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
if (log)
- log->Printf ("SBThread(%p)::Resume() => %i", exe_ctx.GetThreadPtr(), result);
+ log->Printf ("SBThread(%p)::Resume() => %i",
+ static_cast<void*>(exe_ctx.GetThreadPtr()), result);
return result;
}
@@ -1070,8 +1214,10 @@ SBThread::GetProcess ()
{
SBStream frame_desc_strm;
sb_process.GetDescription (frame_desc_strm);
- log->Printf ("SBThread(%p)::GetProcess () => SBProcess(%p): %s", exe_ctx.GetThreadPtr(),
- sb_process.GetSP().get(), frame_desc_strm.GetData());
+ log->Printf ("SBThread(%p)::GetProcess () => SBProcess(%p): %s",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ static_cast<void*>(sb_process.GetSP().get()),
+ frame_desc_strm.GetData());
}
return sb_process;
@@ -1096,12 +1242,14 @@ SBThread::GetNumFrames ()
else
{
if (log)
- log->Printf ("SBThread(%p)::GetNumFrames() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetNumFrames() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
if (log)
- log->Printf ("SBThread(%p)::GetNumFrames () => %u", exe_ctx.GetThreadPtr(), num_frames);
+ log->Printf ("SBThread(%p)::GetNumFrames () => %u",
+ static_cast<void*>(exe_ctx.GetThreadPtr()), num_frames);
return num_frames;
}
@@ -1127,7 +1275,8 @@ SBThread::GetFrameAtIndex (uint32_t idx)
else
{
if (log)
- log->Printf ("SBThread(%p)::GetFrameAtIndex() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetFrameAtIndex() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
@@ -1135,8 +1284,10 @@ SBThread::GetFrameAtIndex (uint32_t idx)
{
SBStream frame_desc_strm;
sb_frame.GetDescription (frame_desc_strm);
- log->Printf ("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s",
- exe_ctx.GetThreadPtr(), idx, frame_sp.get(), frame_desc_strm.GetData());
+ log->Printf ("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s",
+ static_cast<void*>(exe_ctx.GetThreadPtr()), idx,
+ static_cast<void*>(frame_sp.get()),
+ frame_desc_strm.GetData());
}
return sb_frame;
@@ -1163,7 +1314,8 @@ SBThread::GetSelectedFrame ()
else
{
if (log)
- log->Printf ("SBThread(%p)::GetSelectedFrame() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetSelectedFrame() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
@@ -1171,8 +1323,10 @@ SBThread::GetSelectedFrame ()
{
SBStream frame_desc_strm;
sb_frame.GetDescription (frame_desc_strm);
- log->Printf ("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s",
- exe_ctx.GetThreadPtr(), frame_sp.get(), frame_desc_strm.GetData());
+ log->Printf ("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ static_cast<void*>(frame_sp.get()),
+ frame_desc_strm.GetData());
}
return sb_frame;
@@ -1204,7 +1358,8 @@ SBThread::SetSelectedFrame (uint32_t idx)
else
{
if (log)
- log->Printf ("SBThread(%p)::SetSelectedFrame() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::SetSelectedFrame() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
@@ -1212,8 +1367,10 @@ SBThread::SetSelectedFrame (uint32_t idx)
{
SBStream frame_desc_strm;
sb_frame.GetDescription (frame_desc_strm);
- log->Printf ("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s",
- exe_ctx.GetThreadPtr(), idx, frame_sp.get(), frame_desc_strm.GetData());
+ log->Printf ("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s",
+ static_cast<void*>(exe_ctx.GetThreadPtr()), idx,
+ static_cast<void*>(frame_sp.get()),
+ frame_desc_strm.GetData());
}
return sb_frame;
}
@@ -1316,7 +1473,11 @@ 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'", exe_ctx.GetThreadPtr(), new_thread_sp.get(), new_thread_sp->GetQueueID(), queue_name);
+ log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => new extended Thread created (%p) with queue_id 0x%" PRIx64 " queue name '%s'",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ static_cast<void*>(new_thread_sp.get()),
+ new_thread_sp->GetQueueID(),
+ queue_name);
}
}
}
@@ -1326,10 +1487,14 @@ SBThread::GetExtendedBacktraceThread (const char *type)
else
{
if (log)
- log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => error: process is running",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
}
}
+ if (log && sb_origin_thread.IsValid() == false)
+ log->Printf("SBThread(%p)::GetExtendedBacktraceThread() is not returning a Valid thread",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
return sb_origin_thread;
}
@@ -1341,3 +1506,12 @@ SBThread::GetExtendedBacktraceOriginatingIndexID ()
return thread_sp->GetExtendedBacktraceOriginatingIndexID();
return LLDB_INVALID_INDEX32;
}
+
+bool
+SBThread::SafeToCallFunctions ()
+{
+ ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
+ if (thread_sp)
+ return thread_sp->SafeToCallFunctions();
+ return true;
+}
diff --git a/source/API/SBType.cpp b/source/API/SBType.cpp
index 5ca7ddf3d813..064fb32c953f 100644
--- a/source/API/SBType.cpp
+++ b/source/API/SBType.cpp
@@ -9,6 +9,7 @@
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBType.h"
+#include "lldb/API/SBTypeEnumMember.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
@@ -17,6 +18,8 @@
#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Symbol/Type.h"
+#include "clang/AST/Decl.h"
+
using namespace lldb;
using namespace lldb_private;
using namespace clang;
@@ -364,6 +367,27 @@ SBType::GetVirtualBaseClassAtIndex (uint32_t idx)
return sb_type_member;
}
+SBTypeEnumMemberList
+SBType::GetEnumMembers ()
+{
+ SBTypeEnumMemberList sb_enum_member_list;
+ if (IsValid())
+ {
+ const clang::EnumDecl *enum_decl = m_opaque_sp->GetClangASTType(true).GetFullyUnqualifiedType().GetAsEnumDecl();
+ if (enum_decl)
+ {
+ clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
+ for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
+ {
+ SBTypeEnumMember enum_member;
+ enum_member.reset(new TypeEnumMemberImpl(*enum_pos, ClangASTType(m_opaque_sp->GetClangASTContext(true), enum_decl->getIntegerType())));
+ sb_enum_member_list.Append(enum_member);
+ }
+ }
+ }
+ return sb_enum_member_list;
+}
+
SBTypeMember
SBType::GetFieldAtIndex (uint32_t idx)
{
@@ -414,6 +438,14 @@ SBType::GetName()
return m_opaque_sp->GetName().GetCString();
}
+const char *
+SBType::GetDisplayTypeName ()
+{
+ if (!IsValid())
+ return "";
+ return m_opaque_sp->GetDisplayTypeName().GetCString();
+}
+
lldb::TypeClass
SBType::GetTypeClass ()
{
diff --git a/source/API/SBTypeEnumMember.cpp b/source/API/SBTypeEnumMember.cpp
new file mode 100644
index 000000000000..47c57dd213fb
--- /dev/null
+++ b/source/API/SBTypeEnumMember.cpp
@@ -0,0 +1,192 @@
+//===-- SBTypeEnumMember.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/SBDefines.h"
+#include "lldb/API/SBType.h"
+#include "lldb/API/SBTypeEnumMember.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/Type.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace clang;
+
+SBTypeEnumMember::SBTypeEnumMember() :
+ m_opaque_sp()
+{
+}
+
+SBTypeEnumMember::~SBTypeEnumMember()
+{
+}
+SBTypeEnumMember::SBTypeEnumMember (const lldb::TypeEnumMemberImplSP &enum_member_sp) :
+ m_opaque_sp(enum_member_sp)
+{
+}
+
+SBTypeEnumMember::SBTypeEnumMember (const SBTypeEnumMember& rhs) :
+ m_opaque_sp()
+{
+ if (this != &rhs)
+ {
+ if (rhs.IsValid())
+ m_opaque_sp.reset(new TypeEnumMemberImpl(rhs.ref()));
+ }
+}
+
+SBTypeEnumMember&
+SBTypeEnumMember::operator = (const SBTypeEnumMember& rhs)
+{
+ if (this != &rhs)
+ {
+ if (rhs.IsValid())
+ m_opaque_sp.reset(new TypeEnumMemberImpl(rhs.ref()));
+ }
+ return *this;
+}
+
+bool
+SBTypeEnumMember::IsValid() const
+{
+ return m_opaque_sp.get();
+}
+
+const char *
+SBTypeEnumMember::GetName ()
+{
+ if (m_opaque_sp.get())
+ return m_opaque_sp->GetName().GetCString();
+ return NULL;
+}
+
+int64_t
+SBTypeEnumMember::GetValueAsSigned()
+{
+ if (m_opaque_sp.get())
+ return m_opaque_sp->GetValueAsSigned();
+ return 0;
+}
+
+uint64_t
+SBTypeEnumMember::GetValueAsUnsigned()
+{
+ if (m_opaque_sp.get())
+ return m_opaque_sp->GetValueAsUnsigned();
+ return 0;
+}
+
+SBType
+SBTypeEnumMember::GetType ()
+{
+ SBType sb_type;
+ if (m_opaque_sp.get())
+ {
+ sb_type.SetSP(m_opaque_sp->GetIntegerType());
+ }
+ return sb_type;
+
+}
+
+void
+SBTypeEnumMember::reset(TypeEnumMemberImpl *type_member_impl)
+{
+ m_opaque_sp.reset(type_member_impl);
+}
+
+TypeEnumMemberImpl &
+SBTypeEnumMember::ref ()
+{
+ if (m_opaque_sp.get() == NULL)
+ m_opaque_sp.reset (new TypeEnumMemberImpl());
+ return *m_opaque_sp.get();
+}
+
+const TypeEnumMemberImpl &
+SBTypeEnumMember::ref () const
+{
+ return *m_opaque_sp.get();
+}
+
+
+SBTypeEnumMemberList::SBTypeEnumMemberList() :
+ m_opaque_ap(new TypeEnumMemberListImpl())
+{
+}
+
+SBTypeEnumMemberList::SBTypeEnumMemberList(const SBTypeEnumMemberList& rhs) :
+ m_opaque_ap(new TypeEnumMemberListImpl())
+{
+ for (uint32_t i = 0, rhs_size = const_cast<SBTypeEnumMemberList&>(rhs).GetSize(); i < rhs_size; i++)
+ Append(const_cast<SBTypeEnumMemberList&>(rhs).GetTypeEnumMemberAtIndex(i));
+}
+
+bool
+SBTypeEnumMemberList::IsValid ()
+{
+ return (m_opaque_ap.get() != NULL);
+}
+
+SBTypeEnumMemberList&
+SBTypeEnumMemberList::operator = (const SBTypeEnumMemberList& rhs)
+{
+ if (this != &rhs)
+ {
+ m_opaque_ap.reset (new TypeEnumMemberListImpl());
+ for (uint32_t i = 0, rhs_size = const_cast<SBTypeEnumMemberList&>(rhs).GetSize(); i < rhs_size; i++)
+ Append(const_cast<SBTypeEnumMemberList&>(rhs).GetTypeEnumMemberAtIndex(i));
+ }
+ return *this;
+}
+
+void
+SBTypeEnumMemberList::Append (SBTypeEnumMember enum_member)
+{
+ if (enum_member.IsValid())
+ m_opaque_ap->Append (enum_member.m_opaque_sp);
+}
+
+SBTypeEnumMember
+SBTypeEnumMemberList::GetTypeEnumMemberAtIndex(uint32_t index)
+{
+ if (m_opaque_ap.get())
+ return SBTypeEnumMember(m_opaque_ap->GetTypeEnumMemberAtIndex(index));
+ return SBTypeEnumMember();
+}
+
+uint32_t
+SBTypeEnumMemberList::GetSize()
+{
+ return m_opaque_ap->GetSize();
+}
+
+SBTypeEnumMemberList::~SBTypeEnumMemberList()
+{
+}
+
+bool
+SBTypeEnumMember::GetDescription (lldb::SBStream &description,
+ lldb::DescriptionLevel description_level)
+{
+ Stream &strm = description.ref();
+
+ if (m_opaque_sp.get())
+ {
+ if( m_opaque_sp->GetIntegerType()->GetDescription(strm, description_level) )
+ {
+ strm.Printf(" %s", m_opaque_sp->GetName().GetCString());
+ }
+ }
+ else
+ {
+ strm.PutCString ("No value");
+ }
+ return true;
+}
diff --git a/source/API/SBUnixSignals.cpp b/source/API/SBUnixSignals.cpp
new file mode 100644
index 000000000000..ca321d82fd60
--- /dev/null
+++ b/source/API/SBUnixSignals.cpp
@@ -0,0 +1,199 @@
+//===-- SBUnixSignals.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-defines.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/UnixSignals.h"
+#include "lldb/Core/Log.h"
+
+#include "lldb/API/SBUnixSignals.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBUnixSignals::SBUnixSignals ()
+{}
+
+SBUnixSignals::SBUnixSignals (const SBUnixSignals &rhs) :
+ m_opaque_wp(rhs.m_opaque_wp)
+{
+}
+
+SBUnixSignals::SBUnixSignals (ProcessSP &process_sp) :
+ m_opaque_wp(process_sp)
+{
+}
+
+const SBUnixSignals&
+SBUnixSignals::operator = (const SBUnixSignals& rhs)
+{
+ if (this != &rhs)
+ m_opaque_wp = rhs.m_opaque_wp;
+ return *this;
+}
+
+SBUnixSignals::~SBUnixSignals()
+{
+}
+
+ProcessSP
+SBUnixSignals::GetSP() const
+{
+ return m_opaque_wp.lock();
+}
+
+void
+SBUnixSignals::SetSP (const ProcessSP &process_sp)
+{
+ m_opaque_wp = process_sp;
+}
+
+void
+SBUnixSignals::Clear ()
+{
+ m_opaque_wp.reset();
+}
+
+bool
+SBUnixSignals::IsValid() const
+{
+ return (bool) GetSP();
+}
+
+const char *
+SBUnixSignals::GetSignalAsCString (int32_t signo) const
+{
+ ProcessSP process_sp(GetSP());
+ if (process_sp) return process_sp->GetUnixSignals().GetSignalAsCString(signo);
+ return NULL;
+}
+
+int32_t
+SBUnixSignals::GetSignalNumberFromName (const char *name) const
+{
+ ProcessSP process_sp(GetSP());
+ if (process_sp) return process_sp->GetUnixSignals().GetSignalNumberFromName(name);
+ return -1;
+}
+
+bool
+SBUnixSignals::GetShouldSuppress (int32_t signo) const
+{
+ ProcessSP process_sp(GetSP());
+ if (process_sp) return process_sp->GetUnixSignals().GetShouldSuppress(signo);
+ return false;
+}
+
+bool
+SBUnixSignals::SetShouldSuppress (int32_t signo, bool value)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ ProcessSP process_sp(GetSP());
+
+ if (log)
+ {
+ log->Printf ("SBUnixSignals(%p)::SetShouldSuppress (signo=%d, value=%d)",
+ static_cast<void*>(process_sp.get()),
+ signo,
+ value);
+ }
+
+ if (process_sp) return process_sp->GetUnixSignals().SetShouldSuppress(signo, value);
+ return false;
+}
+
+bool
+SBUnixSignals::GetShouldStop (int32_t signo) const
+{
+ ProcessSP process_sp(GetSP());
+ if (process_sp) return process_sp->GetUnixSignals().GetShouldStop(signo);
+ return false;
+}
+
+bool
+SBUnixSignals::SetShouldStop (int32_t signo, bool value)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ ProcessSP process_sp(GetSP());
+
+ if (log)
+ {
+ log->Printf ("SBUnixSignals(%p)::SetShouldStop (signo=%d, value=%d)",
+ static_cast<void*>(process_sp.get()),
+ signo,
+ value);
+ }
+
+ if (process_sp) return process_sp->GetUnixSignals().SetShouldStop(signo, value);
+ return false;
+}
+
+bool
+SBUnixSignals::GetShouldNotify (int32_t signo) const
+{
+ ProcessSP process_sp(GetSP());
+ if (process_sp) return process_sp->GetUnixSignals().GetShouldNotify(signo);
+ return false;
+}
+
+bool
+SBUnixSignals::SetShouldNotify (int32_t signo, bool value)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ ProcessSP process_sp(GetSP());
+
+ if (log)
+ {
+ log->Printf ("SBUnixSignals(%p)::SetShouldNotify (signo=%d, value=%d)",
+ static_cast<void*>(process_sp.get()),
+ signo,
+ value);
+ }
+
+ if (process_sp) return process_sp->GetUnixSignals().SetShouldNotify(signo, value);
+ return false;
+}
+
+int32_t
+SBUnixSignals::GetNumSignals () const
+{
+ if (auto process_sp = GetSP())
+ {
+ // only valid while we hold process_sp
+ UnixSignals *unix_signals_ptr = &process_sp->GetUnixSignals();
+ int32_t num_signals = 0;
+ for (int32_t signo = unix_signals_ptr->GetFirstSignalNumber();
+ signo != LLDB_INVALID_SIGNAL_NUMBER;
+ signo = unix_signals_ptr->GetNextSignalNumber(signo))
+ {
+ num_signals++;
+ }
+ return num_signals;
+ }
+ return LLDB_INVALID_SIGNAL_NUMBER;
+}
+
+int32_t
+SBUnixSignals::GetSignalAtIndex (int32_t index) const
+{
+ if (auto process_sp = GetSP())
+ {
+ // only valid while we hold process_sp
+ UnixSignals *unix_signals_ptr = &process_sp->GetUnixSignals();
+ int32_t idx = 0;
+ for (int32_t signo = unix_signals_ptr->GetFirstSignalNumber();
+ signo != LLDB_INVALID_SIGNAL_NUMBER;
+ signo = unix_signals_ptr->GetNextSignalNumber(signo))
+ {
+ if (index == idx) return signo;
+ idx++;
+ }
+ }
+ return LLDB_INVALID_SIGNAL_NUMBER;
+}
diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp
index 4bd018352ff2..3a9621b1e3bc 100644
--- a/source/API/SBValue.cpp
+++ b/source/API/SBValue.cpp
@@ -58,7 +58,7 @@ public:
ValueImpl ()
{
}
-
+
ValueImpl (lldb::ValueObjectSP in_valobj_sp,
lldb::DynamicValueType use_dynamic,
bool use_synthetic,
@@ -71,7 +71,7 @@ public:
if (!m_name.IsEmpty() && m_valobj_sp)
m_valobj_sp->SetName(m_name);
}
-
+
ValueImpl (const ValueImpl& rhs) :
m_valobj_sp(rhs.m_valobj_sp),
m_use_dynamic(rhs.m_use_dynamic),
@@ -79,7 +79,7 @@ public:
m_name (rhs.m_name)
{
}
-
+
ValueImpl &
operator = (const ValueImpl &rhs)
{
@@ -92,7 +92,7 @@ public:
}
return *this;
}
-
+
bool
IsValid ()
{
@@ -115,13 +115,13 @@ public:
return false;
}
}
-
+
lldb::ValueObjectSP
GetRootSP ()
{
return m_valobj_sp;
}
-
+
lldb::ValueObjectSP
GetSP (Process::StopLocker &stop_locker, Mutex::Locker &api_locker, Error &error)
{
@@ -131,26 +131,27 @@ public:
error.SetErrorString("invalid value object");
return m_valobj_sp;
}
-
+
lldb::ValueObjectSP value_sp = m_valobj_sp;
-
+
Target *target = value_sp->GetTargetSP().get();
if (target)
api_locker.Lock(target->GetAPIMutex());
else
return ValueObjectSP();
-
+
ProcessSP process_sp(value_sp->GetProcessSP());
if (process_sp && !stop_locker.TryLock (&process_sp->GetRunLock()))
{
// We don't allow people to play around with ValueObject if the process is running.
// If you want to look at values, pause the process, then look.
if (log)
- log->Printf ("SBValue(%p)::GetSP() => error: process is running", value_sp.get());
+ log->Printf ("SBValue(%p)::GetSP() => error: process is running",
+ static_cast<void*>(value_sp.get()));
error.SetErrorString ("process must be stopped.");
return ValueObjectSP();
}
-
+
if (value_sp->GetDynamicValue(m_use_dynamic))
value_sp = value_sp->GetDynamicValue(m_use_dynamic);
if (value_sp->GetSyntheticValue(m_use_synthetic))
@@ -159,34 +160,34 @@ public:
error.SetErrorString("invalid value object");
if (!m_name.IsEmpty())
value_sp->SetName(m_name);
-
+
return value_sp;
}
-
+
void
SetUseDynamic (lldb::DynamicValueType use_dynamic)
{
m_use_dynamic = use_dynamic;
}
-
+
void
SetUseSynthetic (bool use_synthetic)
{
m_use_synthetic = use_synthetic;
}
-
+
lldb::DynamicValueType
GetUseDynamic ()
{
return m_use_dynamic;
}
-
+
bool
GetUseSynthetic ()
{
return m_use_synthetic;
}
-
+
// All the derived values that we would make from the m_valobj_sp will share
// the ExecutionContext with m_valobj_sp, so we don't need to do the calculations
// in GetSP to return the Target, Process, Thread or Frame. It is convenient to
@@ -199,7 +200,7 @@ public:
else
return TargetSP();
}
-
+
ProcessSP
GetProcessSP ()
{
@@ -208,7 +209,7 @@ public:
else
return ProcessSP();
}
-
+
ThreadSP
GetThreadSP ()
{
@@ -217,7 +218,7 @@ public:
else
return ThreadSP();
}
-
+
StackFrameSP
GetFrameSP ()
{
@@ -226,7 +227,7 @@ public:
else
return StackFrameSP();
}
-
+
private:
lldb::ValueObjectSP m_valobj_sp;
lldb::DynamicValueType m_use_dynamic;
@@ -337,16 +338,18 @@ SBValue::GetName()
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
name = value_sp->GetName().GetCString();
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
{
if (name)
- log->Printf ("SBValue(%p)::GetName () => \"%s\"", value_sp.get(), name);
+ log->Printf ("SBValue(%p)::GetName () => \"%s\"",
+ static_cast<void*>(value_sp.get()), name);
else
- log->Printf ("SBValue(%p)::GetName () => NULL", value_sp.get());
+ log->Printf ("SBValue(%p)::GetName () => NULL",
+ static_cast<void*>(value_sp.get()));
}
-
+
return name;
}
@@ -361,13 +364,40 @@ SBValue::GetTypeName ()
{
name = value_sp->GetQualifiedTypeName().GetCString();
}
+
+ if (log)
+ {
+ if (name)
+ log->Printf ("SBValue(%p)::GetTypeName () => \"%s\"",
+ static_cast<void*>(value_sp.get()), name);
+ else
+ log->Printf ("SBValue(%p)::GetTypeName () => NULL",
+ static_cast<void*>(value_sp.get()));
+ }
+
+ return name;
+}
+
+const char *
+SBValue::GetDisplayTypeName ()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ const char *name = NULL;
+ ValueLocker locker;
+ lldb::ValueObjectSP value_sp(GetSP(locker));
+ if (value_sp)
+ {
+ name = value_sp->GetDisplayTypeName().GetCString();
+ }
if (log)
{
if (name)
- log->Printf ("SBValue(%p)::GetTypeName () => \"%s\"", value_sp.get(), name);
+ log->Printf ("SBValue(%p)::GetTypeName () => \"%s\"",
+ static_cast<void*>(value_sp.get()), name);
else
- log->Printf ("SBValue(%p)::GetTypeName () => NULL", value_sp.get());
+ log->Printf ("SBValue(%p)::GetTypeName () => NULL",
+ static_cast<void*>(value_sp.get()));
}
return name;
@@ -378,17 +408,19 @@ SBValue::GetByteSize ()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
size_t result = 0;
-
+
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
{
result = value_sp->GetByteSize();
}
-
+
if (log)
- log->Printf ("SBValue(%p)::GetByteSize () => %" PRIu64, value_sp.get(), (uint64_t)result);
-
+ log->Printf ("SBValue(%p)::GetByteSize () => %" PRIu64,
+ static_cast<void*>(value_sp.get()),
+ static_cast<uint64_t>(result));
+
return result;
}
@@ -396,18 +428,19 @@ bool
SBValue::IsInScope ()
{
bool result = false;
-
+
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
{
result = value_sp->IsInScope ();
}
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBValue(%p)::IsInScope () => %i", value_sp.get(), result);
-
+ log->Printf ("SBValue(%p)::IsInScope () => %i",
+ static_cast<void*>(value_sp.get()), result);
+
return result;
}
@@ -415,7 +448,7 @@ const char *
SBValue::GetValue ()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
const char *cstr = NULL;
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
@@ -426,11 +459,13 @@ SBValue::GetValue ()
if (log)
{
if (cstr)
- log->Printf ("SBValue(%p)::GetValue() => \"%s\"", value_sp.get(), cstr);
+ log->Printf ("SBValue(%p)::GetValue() => \"%s\"",
+ static_cast<void*>(value_sp.get()), cstr);
else
- log->Printf ("SBValue(%p)::GetValue() => NULL", value_sp.get());
+ log->Printf ("SBValue(%p)::GetValue() => NULL",
+ static_cast<void*>(value_sp.get()));
}
-
+
return cstr;
}
@@ -442,20 +477,44 @@ SBValue::GetValueType ()
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
result = value_sp->GetValueType();
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
{
switch (result)
{
- case eValueTypeInvalid: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeInvalid", value_sp.get()); break;
- case eValueTypeVariableGlobal: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableGlobal", value_sp.get()); break;
- case eValueTypeVariableStatic: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableStatic", value_sp.get()); break;
- case eValueTypeVariableArgument:log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableArgument", value_sp.get()); break;
- case eValueTypeVariableLocal: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableLocal", value_sp.get()); break;
- case eValueTypeRegister: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegister", value_sp.get()); break;
- case eValueTypeRegisterSet: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegisterSet", value_sp.get()); break;
- case eValueTypeConstResult: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeConstResult", value_sp.get()); break;
+ case eValueTypeInvalid:
+ log->Printf ("SBValue(%p)::GetValueType () => eValueTypeInvalid",
+ static_cast<void*>(value_sp.get()));
+ break;
+ case eValueTypeVariableGlobal:
+ log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableGlobal",
+ static_cast<void*>(value_sp.get()));
+ break;
+ case eValueTypeVariableStatic:
+ log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableStatic",
+ static_cast<void*>(value_sp.get()));
+ break;
+ case eValueTypeVariableArgument:
+ log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableArgument",
+ static_cast<void*>(value_sp.get()));
+ break;
+ case eValueTypeVariableLocal:
+ log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableLocal",
+ static_cast<void*>(value_sp.get()));
+ break;
+ case eValueTypeRegister:
+ log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegister",
+ static_cast<void*>(value_sp.get()));
+ break;
+ case eValueTypeRegisterSet:
+ log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegisterSet",
+ static_cast<void*>(value_sp.get()));
+ break;
+ case eValueTypeConstResult:
+ log->Printf ("SBValue(%p)::GetValueType () => eValueTypeConstResult",
+ static_cast<void*>(value_sp.get()));
+ break;
}
}
return result;
@@ -475,9 +534,11 @@ SBValue::GetObjectDescription ()
if (log)
{
if (cstr)
- log->Printf ("SBValue(%p)::GetObjectDescription() => \"%s\"", value_sp.get(), cstr);
+ log->Printf ("SBValue(%p)::GetObjectDescription() => \"%s\"",
+ static_cast<void*>(value_sp.get()), cstr);
else
- log->Printf ("SBValue(%p)::GetObjectDescription() => NULL", value_sp.get());
+ log->Printf ("SBValue(%p)::GetObjectDescription() => NULL",
+ static_cast<void*>(value_sp.get()));
}
return cstr;
}
@@ -498,9 +559,12 @@ SBValue::GetType()
if (log)
{
if (type_sp)
- log->Printf ("SBValue(%p)::GetType => SBType(%p)", value_sp.get(), type_sp.get());
+ log->Printf ("SBValue(%p)::GetType => SBType(%p)",
+ static_cast<void*>(value_sp.get()),
+ static_cast<void*>(type_sp.get()));
else
- log->Printf ("SBValue(%p)::GetType => NULL", value_sp.get());
+ log->Printf ("SBValue(%p)::GetType => NULL",
+ static_cast<void*>(value_sp.get()));
}
return sb_type;
}
@@ -517,8 +581,9 @@ SBValue::GetValueDidChange ()
result = value_sp->GetValueDidChange ();
}
if (log)
- log->Printf ("SBValue(%p)::GetValueDidChange() => %i", value_sp.get(), result);
-
+ log->Printf ("SBValue(%p)::GetValueDidChange() => %i",
+ static_cast<void*>(value_sp.get()), result);
+
return result;
}
@@ -537,9 +602,11 @@ SBValue::GetSummary ()
if (log)
{
if (cstr)
- log->Printf ("SBValue(%p)::GetSummary() => \"%s\"", value_sp.get(), cstr);
+ log->Printf ("SBValue(%p)::GetSummary() => \"%s\"",
+ static_cast<void*>(value_sp.get()), cstr);
else
- log->Printf ("SBValue(%p)::GetSummary() => NULL", value_sp.get());
+ log->Printf ("SBValue(%p)::GetSummary() => NULL",
+ static_cast<void*>(value_sp.get()));
}
return cstr;
}
@@ -559,9 +626,11 @@ SBValue::GetLocation ()
if (log)
{
if (cstr)
- log->Printf ("SBValue(%p)::GetLocation() => \"%s\"", value_sp.get(), cstr);
+ log->Printf ("SBValue(%p)::GetLocation() => \"%s\"",
+ static_cast<void*>(value_sp.get()), cstr);
else
- log->Printf ("SBValue(%p)::GetLocation() => NULL", value_sp.get());
+ log->Printf ("SBValue(%p)::GetLocation() => NULL",
+ static_cast<void*>(value_sp.get()));
}
return cstr;
}
@@ -587,10 +656,11 @@ SBValue::SetValueFromCString (const char *value_str, lldb::SBError& error)
}
else
error.SetErrorStringWithFormat ("Could not get value: %s", locker.GetError().AsCString());
-
+
if (log)
- log->Printf ("SBValue(%p)::SetValueFromCString(\"%s\") => %i", value_sp.get(), value_str, success);
-
+ log->Printf ("SBValue(%p)::SetValueFromCString(\"%s\") => %i",
+ static_cast<void*>(value_sp.get()), value_str, success);
+
return success;
}
@@ -698,11 +768,11 @@ SBValue::CreateChildAtOffset (const char *name, uint32_t offset, SBType type)
{
if (new_value_sp)
log->Printf ("SBValue(%p)::CreateChildAtOffset => \"%s\"",
- value_sp.get(),
+ static_cast<void*>(value_sp.get()),
new_value_sp->GetName().AsCString());
else
log->Printf ("SBValue(%p)::CreateChildAtOffset => NULL",
- value_sp.get());
+ static_cast<void*>(value_sp.get()));
}
return sb_value;
}
@@ -757,15 +827,11 @@ SBValue::CreateValueFromExpression (const char *name, const char *expression, SB
{
if (new_value_sp)
log->Printf ("SBValue(%p)::CreateValueFromExpression(name=\"%s\", expression=\"%s\") => SBValue (%p)",
- value_sp.get(),
- name,
- expression,
- new_value_sp.get());
+ static_cast<void*>(value_sp.get()), name, expression,
+ static_cast<void*>(new_value_sp.get()));
else
log->Printf ("SBValue(%p)::CreateValueFromExpression(name=\"%s\", expression=\"%s\") => NULL",
- value_sp.get(),
- name,
- expression);
+ static_cast<void*>(value_sp.get()), name, expression);
}
return sb_value;
}
@@ -784,7 +850,7 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, SBType s
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,
@@ -792,7 +858,7 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, SBType s
buffer,
exe_ctx.GetByteOrder(),
exe_ctx.GetAddressByteSize()));
-
+
if (ptr_result_valobj_sp)
{
ptr_result_valobj_sp->GetValue().SetValueType(Value::eValueTypeLoadAddress);
@@ -808,9 +874,12 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, SBType s
if (log)
{
if (new_value_sp)
- log->Printf ("SBValue(%p)::CreateValueFromAddress => \"%s\"", value_sp.get(), new_value_sp->GetName().AsCString());
+ log->Printf ("SBValue(%p)::CreateValueFromAddress => \"%s\"",
+ static_cast<void*>(value_sp.get()),
+ new_value_sp->GetName().AsCString());
else
- log->Printf ("SBValue(%p)::CreateValueFromAddress => NULL", value_sp.get());
+ log->Printf ("SBValue(%p)::CreateValueFromAddress => NULL",
+ static_cast<void*>(value_sp.get()));
}
return sb_value;
}
@@ -825,7 +894,7 @@ 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),
@@ -838,9 +907,12 @@ SBValue::CreateValueFromData (const char* name, SBData data, SBType type)
if (log)
{
if (new_value_sp)
- log->Printf ("SBValue(%p)::CreateValueFromData => \"%s\"", value_sp.get(), new_value_sp->GetName().AsCString());
+ log->Printf ("SBValue(%p)::CreateValueFromData => \"%s\"",
+ static_cast<void*>(value_sp.get()),
+ new_value_sp->GetName().AsCString());
else
- log->Printf ("SBValue(%p)::CreateValueFromData => NULL", value_sp.get());
+ log->Printf ("SBValue(%p)::CreateValueFromData => NULL",
+ static_cast<void*>(value_sp.get()));
}
return sb_value;
}
@@ -865,7 +937,7 @@ SBValue::GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic, bool
{
lldb::ValueObjectSP child_sp;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
@@ -884,12 +956,14 @@ SBValue::GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic, bool
}
}
}
-
+
SBValue sb_value;
sb_value.SetSP (child_sp, use_dynamic, GetPreferSyntheticValue());
if (log)
- log->Printf ("SBValue(%p)::GetChildAtIndex (%u) => SBValue(%p)", value_sp.get(), idx, value_sp.get());
-
+ log->Printf ("SBValue(%p)::GetChildAtIndex (%u) => SBValue(%p)",
+ static_cast<void*>(value_sp.get()), idx,
+ static_cast<void*>(value_sp.get()));
+
return sb_value;
}
@@ -907,9 +981,11 @@ SBValue::GetIndexOfChildWithName (const char *name)
if (log)
{
if (idx == UINT32_MAX)
- log->Printf ("SBValue(%p)::GetIndexOfChildWithName (name=\"%s\") => NOT FOUND", value_sp.get(), name);
+ log->Printf ("SBValue(%p)::GetIndexOfChildWithName (name=\"%s\") => NOT FOUND",
+ static_cast<void*>(value_sp.get()), name);
else
- log->Printf ("SBValue(%p)::GetIndexOfChildWithName (name=\"%s\") => %u", value_sp.get(), name, idx);
+ log->Printf ("SBValue(%p)::GetIndexOfChildWithName (name=\"%s\") => %u",
+ static_cast<void*>(value_sp.get()), name, idx);
}
return idx;
}
@@ -921,7 +997,7 @@ SBValue::GetChildMemberWithName (const char *name)
TargetSP target_sp;
if (m_opaque_sp)
target_sp = m_opaque_sp->GetTargetSP();
-
+
if (target_sp)
use_dynamic_value = target_sp->GetPreferDynamicValue();
return GetChildMemberWithName (name, use_dynamic_value);
@@ -932,22 +1008,24 @@ SBValue::GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dy
{
lldb::ValueObjectSP child_sp;
const ConstString str_name (name);
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
+
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
{
child_sp = value_sp->GetChildMemberWithName (str_name, true);
}
-
+
SBValue sb_value;
sb_value.SetSP(child_sp, use_dynamic_value, GetPreferSyntheticValue());
-
+
if (log)
- log->Printf ("SBValue(%p)::GetChildMemberWithName (name=\"%s\") => SBValue(%p)", value_sp.get(), name, value_sp.get());
-
+ log->Printf ("SBValue(%p)::GetChildMemberWithName (name=\"%s\") => SBValue(%p)",
+ static_cast<void*>(value_sp.get()), name,
+ static_cast<void*>(value_sp.get()));
+
return sb_value;
}
@@ -1049,13 +1127,15 @@ SBValue::GetValueForExpressionPath(const char* expr_path)
// using default values for all the fancy options, just do it if you can
child_sp = value_sp->GetValueForExpressionPath(expr_path);
}
-
+
SBValue sb_value;
sb_value.SetSP(child_sp,GetPreferDynamicValue(),GetPreferSyntheticValue());
-
+
if (log)
- log->Printf ("SBValue(%p)::GetValueForExpressionPath (expr_path=\"%s\") => SBValue(%p)", value_sp.get(), expr_path, value_sp.get());
-
+ log->Printf ("SBValue(%p)::GetValueForExpressionPath (expr_path=\"%s\") => SBValue(%p)",
+ static_cast<void*>(value_sp.get()), expr_path,
+ static_cast<void*>(value_sp.get()));
+
return sb_value;
}
@@ -1134,9 +1214,10 @@ SBValue::MightHaveChildren ()
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
has_children = value_sp->MightHaveChildren();
-
+
if (log)
- log->Printf ("SBValue(%p)::MightHaveChildren() => %i", value_sp.get(), has_children);
+ log->Printf ("SBValue(%p)::MightHaveChildren() => %i",
+ static_cast<void*>(value_sp.get()), has_children);
return has_children;
}
@@ -1144,16 +1225,17 @@ uint32_t
SBValue::GetNumChildren ()
{
uint32_t num_children = 0;
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
num_children = value_sp->GetNumChildren();
-
+
if (log)
- log->Printf ("SBValue(%p)::GetNumChildren () => %u", value_sp.get(), num_children);
-
+ log->Printf ("SBValue(%p)::GetNumChildren () => %u",
+ static_cast<void*>(value_sp.get()), num_children);
+
return num_children;
}
@@ -1171,8 +1253,10 @@ SBValue::Dereference ()
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBValue(%p)::Dereference () => SBValue(%p)", value_sp.get(), value_sp.get());
-
+ log->Printf ("SBValue(%p)::Dereference () => SBValue(%p)",
+ static_cast<void*>(value_sp.get()),
+ static_cast<void*>(value_sp.get()));
+
return sb_value;
}
@@ -1180,17 +1264,17 @@ bool
SBValue::TypeIsPointerType ()
{
bool is_ptr_type = false;
-
+
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
is_ptr_type = value_sp->IsPointerType();
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBValue(%p)::TypeIsPointerType () => %i", value_sp.get(), is_ptr_type);
-
-
+ log->Printf ("SBValue(%p)::TypeIsPointerType () => %i",
+ static_cast<void*>(value_sp.get()), is_ptr_type);
+
return is_ptr_type;
}
@@ -1218,9 +1302,12 @@ SBValue::GetTarget()
if (log)
{
if (target_sp.get() == NULL)
- log->Printf ("SBValue(%p)::GetTarget () => NULL", m_opaque_sp.get());
+ log->Printf ("SBValue(%p)::GetTarget () => NULL",
+ static_cast<void*>(m_opaque_sp.get()));
else
- log->Printf ("SBValue(%p)::GetTarget () => %p", m_opaque_sp.get(), target_sp.get());
+ log->Printf ("SBValue(%p)::GetTarget () => %p",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(target_sp.get()));
}
return sb_target;
}
@@ -1239,9 +1326,12 @@ SBValue::GetProcess()
if (log)
{
if (process_sp.get() == NULL)
- log->Printf ("SBValue(%p)::GetProcess () => NULL", m_opaque_sp.get());
+ log->Printf ("SBValue(%p)::GetProcess () => NULL",
+ static_cast<void*>(m_opaque_sp.get()));
else
- log->Printf ("SBValue(%p)::GetProcess () => %p", m_opaque_sp.get(), process_sp.get());
+ log->Printf ("SBValue(%p)::GetProcess () => %p",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(process_sp.get()));
}
return sb_process;
}
@@ -1260,9 +1350,12 @@ SBValue::GetThread()
if (log)
{
if (thread_sp.get() == NULL)
- log->Printf ("SBValue(%p)::GetThread () => NULL", m_opaque_sp.get());
+ log->Printf ("SBValue(%p)::GetThread () => NULL",
+ static_cast<void*>(m_opaque_sp.get()));
else
- log->Printf ("SBValue(%p)::GetThread () => %p", m_opaque_sp.get(), thread_sp.get());
+ log->Printf ("SBValue(%p)::GetThread () => %p",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(thread_sp.get()));
}
return sb_thread;
}
@@ -1281,9 +1374,12 @@ SBValue::GetFrame()
if (log)
{
if (frame_sp.get() == NULL)
- log->Printf ("SBValue(%p)::GetFrame () => NULL", m_opaque_sp.get());
+ log->Printf ("SBValue(%p)::GetFrame () => NULL",
+ static_cast<void*>(m_opaque_sp.get()));
else
- log->Printf ("SBValue(%p)::GetFrame () => %p", m_opaque_sp.get(), frame_sp.get());
+ log->Printf ("SBValue(%p)::GetFrame () => %p",
+ static_cast<void*>(m_opaque_sp.get()),
+ static_cast<void*>(frame_sp.get()));
}
return sb_frame;
}
@@ -1450,8 +1546,10 @@ SBValue::AddressOf()
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBValue(%p)::AddressOf () => SBValue(%p)", value_sp.get(), value_sp.get());
-
+ log->Printf ("SBValue(%p)::AddressOf () => SBValue(%p)",
+ static_cast<void*>(value_sp.get()),
+ static_cast<void*>(value_sp.get()));
+
return sb_value;
}
@@ -1487,8 +1585,9 @@ SBValue::GetLoadAddress()
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBValue(%p)::GetLoadAddress () => (%" PRIu64 ")", value_sp.get(), value);
-
+ log->Printf ("SBValue(%p)::GetLoadAddress () => (%" PRIu64 ")",
+ static_cast<void*>(value_sp.get()), value);
+
return value;
}
@@ -1524,8 +1623,11 @@ SBValue::GetAddress()
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBValue(%p)::GetAddress () => (%s,%" PRIu64 ")", value_sp.get(),
- (addr.GetSection() ? addr.GetSection()->GetName().GetCString() : "NULL"),
+ log->Printf ("SBValue(%p)::GetAddress () => (%s,%" PRIu64 ")",
+ static_cast<void*>(value_sp.get()),
+ (addr.GetSection()
+ ? addr.GetSection()->GetName().GetCString()
+ : "NULL"),
addr.GetOffset());
return SBAddress(new Address(addr));
}
@@ -1551,11 +1653,9 @@ SBValue::GetPointeeData (uint32_t item_idx,
}
if (log)
log->Printf ("SBValue(%p)::GetPointeeData (%d, %d) => SBData(%p)",
- value_sp.get(),
- item_idx,
- item_count,
- sb_data.get());
-
+ static_cast<void*>(value_sp.get()), item_idx, item_count,
+ static_cast<void*>(sb_data.get()));
+
return sb_data;
}
@@ -1569,15 +1669,16 @@ SBValue::GetData ()
if (value_sp)
{
DataExtractorSP data_sp(new DataExtractor());
- value_sp->GetData(*data_sp);
- if (data_sp->GetByteSize() > 0)
+ Error error;
+ value_sp->GetData(*data_sp, error);
+ if (error.Success())
*sb_data = data_sp;
}
if (log)
log->Printf ("SBValue(%p)::GetData () => SBData(%p)",
- value_sp.get(),
- sb_data.get());
-
+ static_cast<void*>(value_sp.get()),
+ static_cast<void*>(sb_data.get()));
+
return sb_data;
}
@@ -1588,25 +1689,26 @@ SBValue::SetData (lldb::SBData &data, SBError &error)
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
bool ret = true;
-
+
if (value_sp)
{
DataExtractor *data_extractor = data.get();
-
+
if (!data_extractor)
{
if (log)
- log->Printf ("SBValue(%p)::SetData() => error: no data to set", value_sp.get());
-
+ log->Printf ("SBValue(%p)::SetData() => error: no data to set",
+ static_cast<void*>(value_sp.get()));
+
error.SetErrorString("No data to set");
ret = false;
}
else
{
Error set_error;
-
+
value_sp->SetData(*data_extractor, set_error);
-
+
if (!set_error.Success())
{
error.SetErrorStringWithFormat("Couldn't set data: %s", set_error.AsCString());
@@ -1619,12 +1721,11 @@ SBValue::SetData (lldb::SBData &data, SBError &error)
error.SetErrorStringWithFormat ("Couldn't set data: could not get SBValue: %s", locker.GetError().AsCString());
ret = false;
}
-
+
if (log)
log->Printf ("SBValue(%p)::SetData (%p) => %s",
- value_sp.get(),
- data.get(),
- ret ? "true" : "false");
+ static_cast<void*>(value_sp.get()),
+ static_cast<void*>(data.get()), ret ? "true" : "false");
return ret;
}
@@ -1647,7 +1748,7 @@ lldb::SBWatchpoint
SBValue::Watch (bool resolve_location, bool read, bool write, SBError &error)
{
SBWatchpoint sb_watchpoint;
-
+
// If the SBValue is not valid, there's no point in even trying to watch it.
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
@@ -1657,29 +1758,29 @@ SBValue::Watch (bool resolve_location, bool read, bool write, SBError &error)
// Read and Write cannot both be false.
if (!read && !write)
return sb_watchpoint;
-
+
// If the value is not in scope, don't try and watch and invalid value
if (!IsInScope())
return sb_watchpoint;
-
+
addr_t addr = GetLoadAddress();
if (addr == LLDB_INVALID_ADDRESS)
return sb_watchpoint;
size_t byte_size = GetByteSize();
if (byte_size == 0)
return sb_watchpoint;
-
+
uint32_t watch_type = 0;
if (read)
watch_type |= LLDB_WATCH_TYPE_READ;
if (write)
watch_type |= LLDB_WATCH_TYPE_WRITE;
-
+
Error rc;
ClangASTType type (value_sp->GetClangType());
WatchpointSP watchpoint_sp = target_sp->CreateWatchpoint(addr, byte_size, &type, watch_type, rc);
error.SetError(rc);
-
+
if (watchpoint_sp)
{
sb_watchpoint.SetSP (watchpoint_sp);
@@ -1700,18 +1801,21 @@ SBValue::Watch (bool resolve_location, bool read, bool write, SBError &error)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBValue(%p)::Watch() => error getting SBValue: %s", value_sp.get(), locker.GetError().AsCString());
-
+ log->Printf ("SBValue(%p)::Watch() => error getting SBValue: %s",
+ static_cast<void*>(value_sp.get()),
+ locker.GetError().AsCString());
+
error.SetErrorStringWithFormat("could not get SBValue: %s", locker.GetError().AsCString());
}
else
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBValue(%p)::Watch() => error getting SBValue: no target", value_sp.get());
+ log->Printf ("SBValue(%p)::Watch() => error getting SBValue: no target",
+ static_cast<void*>(value_sp.get()));
error.SetErrorString("could not set watchpoint, a target is required");
}
-
+
return sb_watchpoint;
}
diff --git a/source/API/SBValueList.cpp b/source/API/SBValueList.cpp
index 46866eb37424..5069ed3f5624 100644
--- a/source/API/SBValueList.cpp
+++ b/source/API/SBValueList.cpp
@@ -99,8 +99,8 @@ SBValueList::SBValueList (const SBValueList &rhs) :
if (log)
{
log->Printf ("SBValueList::SBValueList (rhs.ap=%p) => this.ap = %p",
- (rhs.IsValid() ? rhs.m_opaque_ap.get() : NULL),
- m_opaque_ap.get());
+ static_cast<void*>(rhs.IsValid() ? rhs.m_opaque_ap.get() : NULL),
+ static_cast<void*>(m_opaque_ap.get()));
}
}
@@ -114,9 +114,9 @@ SBValueList::SBValueList (const ValueListImpl *lldb_object_ptr) :
if (log)
{
- log->Printf ("SBValueList::SBValueList (lldb_object_ptr=%p) => this.ap = %p",
- lldb_object_ptr,
- m_opaque_ap.get());
+ log->Printf ("SBValueList::SBValueList (lldb_object_ptr=%p) => this.ap = %p",
+ static_cast<const void*>(lldb_object_ptr),
+ static_cast<void*>(m_opaque_ap.get()));
}
}
@@ -218,7 +218,8 @@ SBValueList::GetValueAtIndex (uint32_t idx) const
SBStream sstr;
sb_value.GetDescription (sstr);
log->Printf ("SBValueList::GetValueAtIndex (this.ap=%p, idx=%d) => SBValue (this.sp = %p, '%s')",
- m_opaque_ap.get(), idx, sb_value.GetSP().get(), sstr.GetData());
+ static_cast<void*>(m_opaque_ap.get()), idx,
+ static_cast<void*>(sb_value.GetSP().get()), sstr.GetData());
}
return sb_value;
@@ -237,7 +238,8 @@ SBValueList::GetSize () const
size = m_opaque_ap->GetSize();
if (log)
- log->Printf ("SBValueList::GetSize (this.ap=%p) => %d", m_opaque_ap.get(), size);
+ log->Printf ("SBValueList::GetSize (this.ap=%p) => %d",
+ static_cast<void*>(m_opaque_ap.get()), size);
return size;
}
diff --git a/source/API/SBWatchpoint.cpp b/source/API/SBWatchpoint.cpp
index 194695c31d5b..1a1a970aaa87 100644
--- a/source/API/SBWatchpoint.cpp
+++ b/source/API/SBWatchpoint.cpp
@@ -42,7 +42,9 @@ SBWatchpoint::SBWatchpoint (const lldb::WatchpointSP &wp_sp) :
SBStream sstr;
GetDescription (sstr, lldb::eDescriptionLevelBrief);
log->Printf ("SBWatchpoint::SBWatchpoint (const lldb::WatchpointSP &wp_sp"
- "=%p) => this.sp = %p (%s)", wp_sp.get(), m_opaque_sp.get(), sstr.GetData());
+ "=%p) => this.sp = %p (%s)",
+ static_cast<void*>(wp_sp.get()),
+ static_cast<void*>(m_opaque_sp.get()), sstr.GetData());
}
}
@@ -77,9 +79,11 @@ SBWatchpoint::GetID ()
if (log)
{
if (watch_id == LLDB_INVALID_WATCH_ID)
- log->Printf ("SBWatchpoint(%p)::GetID () => LLDB_INVALID_WATCH_ID", watchpoint_sp.get());
+ log->Printf ("SBWatchpoint(%p)::GetID () => LLDB_INVALID_WATCH_ID",
+ static_cast<void*>(watchpoint_sp.get()));
else
- log->Printf ("SBWatchpoint(%p)::GetID () => %u", watchpoint_sp.get(), watch_id);
+ log->Printf ("SBWatchpoint(%p)::GetID () => %u",
+ static_cast<void*>(watchpoint_sp.get()), watch_id);
}
return watch_id;
@@ -185,7 +189,8 @@ SBWatchpoint::GetHitCount ()
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBWatchpoint(%p)::GetHitCount () => %u", watchpoint_sp.get(), count);
+ log->Printf ("SBWatchpoint(%p)::GetHitCount () => %u",
+ static_cast<void*>(watchpoint_sp.get()), count);
return count;
}
diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp
index 5ce064fc41a0..7d08170e4aed 100644
--- a/source/Breakpoint/Breakpoint.cpp
+++ b/source/Breakpoint/Breakpoint.cpp
@@ -541,7 +541,7 @@ Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_l
if (!m_kind_description.empty())
{
- if (eDescriptionLevelBrief)
+ if (level == eDescriptionLevelBrief)
{
s->PutCString (GetBreakpointKind());
return;
diff --git a/source/Breakpoint/BreakpointID.cpp b/source/Breakpoint/BreakpointID.cpp
index 9a59e29d007d..9963ed68303a 100644
--- a/source/Breakpoint/BreakpointID.cpp
+++ b/source/Breakpoint/BreakpointID.cpp
@@ -71,7 +71,7 @@ void
BreakpointID::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
if (level == eDescriptionLevelVerbose)
- s->Printf("%p BreakpointID:", this);
+ s->Printf("%p BreakpointID:", static_cast<void*>(this));
if (m_break_id == LLDB_INVALID_BREAK_ID)
s->PutCString ("<invalid>");
diff --git a/source/Breakpoint/BreakpointList.cpp b/source/Breakpoint/BreakpointList.cpp
index 147ad36b0407..650737761547 100644
--- a/source/Breakpoint/BreakpointList.cpp
+++ b/source/Breakpoint/BreakpointList.cpp
@@ -167,7 +167,7 @@ void
BreakpointList::Dump (Stream *s) const
{
Mutex::Locker locker(m_mutex);
- s->Printf("%p: ", this);
+ s->Printf("%p: ", static_cast<const void*>(this));
s->Indent();
s->Printf("BreakpointList with %u Breakpoints:\n", (uint32_t)m_breakpoints.size());
s->IndentMore();
diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp
index 2c75a11e9788..e1ac043ae905 100644
--- a/source/Breakpoint/BreakpointLocation.cpp
+++ b/source/Breakpoint/BreakpointLocation.cpp
@@ -289,7 +289,8 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
if (!m_user_expression_sp->Parse(errors,
exe_ctx,
eExecutionPolicyOnlyWhenNeeded,
- true))
+ true,
+ false))
{
error.SetErrorStringWithFormat("Couldn't parse conditional expression:\n%s",
errors.GetData());
@@ -316,7 +317,7 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
ClangExpressionVariableSP result_variable_sp;
- ExecutionResults result_code =
+ ExpressionResults result_code =
m_user_expression_sp->Execute(execution_errors,
exe_ctx,
options,
@@ -325,11 +326,10 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
bool ret;
- if (result_code == eExecutionCompleted)
+ if (result_code == eExpressionCompleted)
{
if (!result_variable_sp)
{
- ret = false;
error.SetErrorString("Expression did not return a result");
return false;
}
@@ -522,8 +522,15 @@ BreakpointLocation::ClearBreakpointSite ()
{
if (m_bp_site_sp.get())
{
- m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
+ ProcessSP process_sp(m_owner.GetTarget().GetProcessSP());
+ // If the process exists, get it to remove the owner, it will remove the physical implementation
+ // of the breakpoint as well if there are no more owners. Otherwise just remove this owner.
+ if (process_sp)
+ process_sp->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
GetID(), m_bp_site_sp);
+ else
+ m_bp_site_sp->RemoveOwner(GetBreakpoint().GetID(), GetID());
+
m_bp_site_sp.reset();
return true;
}
@@ -627,7 +634,7 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
if (exe_scope == NULL)
exe_scope = target;
- if (eDescriptionLevelInitial)
+ if (level == eDescriptionLevelInitial)
m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
else
m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp
index 917c776e75d2..ae7f863ad090 100644
--- a/source/Breakpoint/BreakpointLocationList.cpp
+++ b/source/Breakpoint/BreakpointLocationList.cpp
@@ -152,7 +152,7 @@ BreakpointLocationList::FindByAddress (const Address &addr) const
void
BreakpointLocationList::Dump (Stream *s) const
{
- s->Printf("%p: ", this);
+ s->Printf("%p: ", static_cast<const void*>(this));
//s->Indent();
Mutex::Locker locker (m_mutex);
s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size());
diff --git a/source/Breakpoint/BreakpointOptions.cpp b/source/Breakpoint/BreakpointOptions.cpp
index 3a4a117695fc..ea8556d0930b 100644
--- a/source/Breakpoint/BreakpointOptions.cpp
+++ b/source/Breakpoint/BreakpointOptions.cpp
@@ -154,7 +154,7 @@ BreakpointOptions::InvokeCallback (StoppointCallbackContext *context,
}
bool
-BreakpointOptions::HasCallback ()
+BreakpointOptions::HasCallback () const
{
return m_callback != BreakpointOptions::NullCallback;
}
diff --git a/source/Breakpoint/BreakpointResolverName.cpp b/source/Breakpoint/BreakpointResolverName.cpp
index cf5d89cb7a8b..3ac3ed06fc70 100644
--- a/source/Breakpoint/BreakpointResolverName.cpp
+++ b/source/Breakpoint/BreakpointResolverName.cpp
@@ -234,7 +234,7 @@ BreakpointResolverName::SearchCallback
if (context.module_sp)
{
context.module_sp->FindFunctions (m_regex,
- !filter_by_cu, // include symbols only if we aren't filterning by CU
+ !filter_by_cu, // include symbols only if we aren't filtering by CU
include_inlines,
append,
func_list);
@@ -264,7 +264,7 @@ BreakpointResolverName::SearchCallback
}
}
- // Remove any duplicates between the funcion list and the symbol list
+ // Remove any duplicates between the function list and the symbol list
SymbolContext sc;
if (func_list.GetSize())
{
diff --git a/source/Breakpoint/BreakpointSite.cpp b/source/Breakpoint/BreakpointSite.cpp
index fa5d8c1f9f81..3cf6d37af379 100644
--- a/source/Breakpoint/BreakpointSite.cpp
+++ b/source/Breakpoint/BreakpointSite.cpp
@@ -32,7 +32,8 @@ BreakpointSite::BreakpointSite
m_saved_opcode(),
m_trap_opcode(),
m_enabled(false), // Need to create it disabled, so the first enable turns it on.
- m_owners()
+ m_owners(),
+ m_owners_mutex(Mutex::eMutexTypeRecursive)
{
m_owners.Add(owner);
}
@@ -60,6 +61,7 @@ BreakpointSite::GetNextID()
bool
BreakpointSite::ShouldStop (StoppointCallbackContext *context)
{
+ Mutex::Locker locker(m_owners_mutex);
IncrementHitCount();
return m_owners.ShouldStop (context);
}
@@ -67,6 +69,7 @@ BreakpointSite::ShouldStop (StoppointCallbackContext *context)
bool
BreakpointSite::IsBreakpointAtThisSite (lldb::break_id_t bp_id)
{
+ Mutex::Locker locker(m_owners_mutex);
const size_t owner_count = m_owners.GetSize();
for (size_t i = 0; i < owner_count; i++)
{
@@ -93,6 +96,7 @@ BreakpointSite::Dump(Stream *s) const
void
BreakpointSite::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
+ Mutex::Locker locker(m_owners_mutex);
if (level != lldb::eDescriptionLevelBrief)
s->Printf ("breakpoint site: %d at 0x%8.8" PRIx64, GetID(), GetLoadAddress());
m_owners.GetDescription (s, level);
@@ -162,12 +166,14 @@ BreakpointSite::SetEnabled (bool enabled)
void
BreakpointSite::AddOwner (const BreakpointLocationSP &owner)
{
+ Mutex::Locker locker(m_owners_mutex);
m_owners.Add(owner);
}
size_t
BreakpointSite::RemoveOwner (lldb::break_id_t break_id, lldb::break_id_t break_loc_id)
{
+ Mutex::Locker locker(m_owners_mutex);
m_owners.Remove(break_id, break_loc_id);
return m_owners.GetSize();
}
@@ -175,18 +181,21 @@ BreakpointSite::RemoveOwner (lldb::break_id_t break_id, lldb::break_id_t break_l
size_t
BreakpointSite::GetNumberOfOwners ()
{
+ Mutex::Locker locker(m_owners_mutex);
return m_owners.GetSize();
}
BreakpointLocationSP
BreakpointSite::GetOwnerAtIndex (size_t index)
{
+ Mutex::Locker locker(m_owners_mutex);
return m_owners.GetByIndex (index);
}
bool
BreakpointSite::ValidForThisThread (Thread *thread)
{
+ Mutex::Locker locker(m_owners_mutex);
return m_owners.ValidForThisThread(thread);
}
diff --git a/source/Breakpoint/BreakpointSiteList.cpp b/source/Breakpoint/BreakpointSiteList.cpp
index 68c4af18ec5e..1eaadb62a384 100644
--- a/source/Breakpoint/BreakpointSiteList.cpp
+++ b/source/Breakpoint/BreakpointSiteList.cpp
@@ -186,7 +186,7 @@ BreakpointSiteList::BreakpointSiteContainsBreakpoint (lldb::break_id_t bp_site_i
void
BreakpointSiteList::Dump (Stream *s) const
{
- s->Printf("%p: ", this);
+ s->Printf("%p: ", static_cast<const void*>(this));
//s->Indent();
s->Printf("BreakpointSiteList with %u BreakpointSites:\n", (uint32_t)m_bp_site_list.size());
s->IndentMore();
diff --git a/source/Breakpoint/WatchpointList.cpp b/source/Breakpoint/WatchpointList.cpp
index 6d62dffd22cc..472bae06b441 100644
--- a/source/Breakpoint/WatchpointList.cpp
+++ b/source/Breakpoint/WatchpointList.cpp
@@ -55,7 +55,7 @@ void
WatchpointList::DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const
{
Mutex::Locker locker (m_mutex);
- s->Printf("%p: ", this);
+ s->Printf("%p: ", static_cast<const void*>(this));
//s->Indent();
s->Printf("WatchpointList with %" PRIu64 " Watchpoints:\n",
(uint64_t)m_watchpoints.size());
diff --git a/source/Commands/CommandCompletions.cpp b/source/Commands/CommandCompletions.cpp
index 970aa692bd27..f0ad4a896739 100644
--- a/source/Commands/CommandCompletions.cpp
+++ b/source/Commands/CommandCompletions.cpp
@@ -30,6 +30,8 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/CleanUp.h"
+#include "llvm/ADT/SmallString.h"
+
using namespace lldb_private;
CommandCompletions::CommonCompletionElement
@@ -221,7 +223,7 @@ DiskFilesOrDirectories
end_ptr = strrchr(partial_name_copy, '/');
// This will store the resolved form of the containing directory
- char containing_part[PATH_MAX];
+ llvm::SmallString<64> containing_part;
if (end_ptr == NULL)
{
@@ -232,14 +234,11 @@ DiskFilesOrDirectories
// Nothing here but the user name. We could just put a slash on the end,
// but for completeness sake we'll resolve the user name and only put a slash
// on the end if it exists.
- char resolved_username[PATH_MAX];
- size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username,
- sizeof (resolved_username));
+ llvm::SmallString<64> resolved_username(partial_name_copy);
+ FileSpec::ResolveUsername (resolved_username);
// Not sure how this would happen, a username longer than PATH_MAX? Still...
- if (resolved_username_len >= sizeof (resolved_username))
- return matches.GetSize();
- else if (resolved_username_len == 0)
+ if (resolved_username.size() == 0)
{
// The user name didn't resolve, let's look in the password database for matches.
// The user name database contains duplicates, and is not in alphabetical order, so
@@ -263,8 +262,7 @@ DiskFilesOrDirectories
else
{
// The containing part is the CWD, and the whole string is the remainder.
- containing_part[0] = '.';
- containing_part[1] = '\0';
+ containing_part = ".";
strcpy(remainder, partial_name_copy);
end_ptr = partial_name_copy;
}
@@ -274,14 +272,11 @@ DiskFilesOrDirectories
if (end_ptr == partial_name_copy)
{
// We're completing a file or directory in the root volume.
- containing_part[0] = '/';
- containing_part[1] = '\0';
+ containing_part = "/";
}
else
{
- size_t len = end_ptr - partial_name_copy;
- memcpy(containing_part, partial_name_copy, len);
- containing_part[len] = '\0';
+ containing_part.append(partial_name_copy, end_ptr);
}
// Push end_ptr past the final "/" and set remainder.
end_ptr++;
@@ -293,11 +288,9 @@ DiskFilesOrDirectories
if (*partial_name_copy == '~')
{
- size_t resolved_username_len = FileSpec::ResolveUsername(containing_part,
- containing_part,
- sizeof (containing_part));
+ FileSpec::ResolveUsername(containing_part);
// User name doesn't exist, we're not getting any further...
- if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part))
+ if (containing_part.empty())
return matches.GetSize();
}
@@ -314,7 +307,7 @@ DiskFilesOrDirectories
parameters.end_ptr = end_ptr;
parameters.baselen = baselen;
- FileSpec::EnumerateDirectory(containing_part, true, true, true, DiskFilesOrDirectoriesCallback, &parameters);
+ FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true, DiskFilesOrDirectoriesCallback, &parameters);
return matches.GetSize();
}
diff --git a/source/Commands/CommandObjectArgs.cpp b/source/Commands/CommandObjectArgs.cpp
index 3b919d11a566..b0fe42bc2446 100644
--- a/source/Commands/CommandObjectArgs.cpp
+++ b/source/Commands/CommandObjectArgs.cpp
@@ -57,13 +57,7 @@ CommandObjectArgs::CommandOptions::SetOptionValue (uint32_t option_idx, const ch
Error error;
const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option)
- {
- default:
- error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
- break;
- }
+ error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
return error;
}
@@ -255,7 +249,7 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
for (arg_index = 0; arg_index < num_args; ++arg_index)
{
- result.GetOutputStream ().Printf ("%zu (%s): ", arg_index, args.GetArgumentAtIndex (arg_index));
+ result.GetOutputStream ().Printf ("%" PRIu64 " (%s): ", (uint64_t)arg_index, args.GetArgumentAtIndex (arg_index));
value_list.GetValueAtIndex (arg_index)->Dump (&result.GetOutputStream ());
result.GetOutputStream ().Printf("\n");
}
@@ -266,7 +260,7 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
OptionDefinition
CommandObjectArgs::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "debug", 'g', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_1, false, "debug", 'g', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp
index c20da7f3ec5c..13bf1278c78c 100644
--- a/source/Commands/CommandObjectBreakpoint.cpp
+++ b/source/Commands/CommandObjectBreakpoint.cpp
@@ -154,9 +154,12 @@ public:
case eLanguageTypeC89:
case eLanguageTypeC:
case eLanguageTypeC99:
+ case eLanguageTypeC11:
m_language = eLanguageTypeC;
break;
case eLanguageTypeC_plus_plus:
+ case eLanguageTypeC_plus_plus_03:
+ case eLanguageTypeC_plus_plus_11:
m_language = eLanguageTypeC_plus_plus;
break;
case eLanguageTypeObjC:
@@ -623,41 +626,41 @@ private:
OptionDefinition
CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
+ { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
"Set the breakpoint only in this shared library. "
"Can repeat this option multiple times to specify multiple shared libraries."},
- { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount,
+ { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount,
"Set the number of times this breakpoint is skipped before stopping." },
- { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"The breakpoint is deleted the first time it causes a stop." },
- { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression,
+ { 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_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadIndex,
+ { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex,
"The breakpoint stops only for the thread whose indeX matches this argument."},
- { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadID,
+ { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadID,
"The breakpoint stops only for the thread whose TID matches this argument."},
- { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadName,
+ { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadName,
"The breakpoint stops only for the thread whose thread name matches this argument."},
- { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Require the breakpoint to use hardware breakpoints."},
- { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, NULL, 0, eArgTypeQueueName,
+ { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeQueueName,
"The breakpoint stops only for threads in the queue whose name is given by this argument."},
- { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
+ { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
"Specifies the source file in which to set this breakpoint. "
"Note, by default lldb only looks for files that are #included if they use the standard include file extensions. "
"To set breakpoints on .c/.cpp/.m/.mm files that are #included, set target.inline-breakpoint-strategy"
" to \"always\"."},
- { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum,
+ { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
"Specifies the line number on which to set this breakpoint."},
// Comment out this option for the moment, as we don't actually use it, but will in the future.
@@ -665,48 +668,48 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
// { 0, false, "column", 'C', OptionParser::eRequiredArgument, NULL, "<column>",
// "Set the breakpoint by source location at this particular column."},
- { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression,
+ { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression,
"Set the breakpoint by address, at the specified address."},
- { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
+ { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
"Set the breakpoint by function name. Can be repeated multiple times to make one breakpoint for multiple names" },
- { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName,
+ { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName,
"Set the breakpoint by fully qualified function names. For C++ this means namespaces and all arguments, and "
"for Objective C this means a full function prototype with class and selector. "
"Can be repeated multiple times to make one breakpoint for multiple names." },
- { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, NULL, 0, eArgTypeSelector,
+ { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeSelector,
"Set the breakpoint by ObjC selector name. Can be repeated multiple times to make one breakpoint for multiple Selectors." },
- { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, NULL, 0, eArgTypeMethod,
+ { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeMethod,
"Set the breakpoint by C++ method names. Can be repeated multiple times to make one breakpoint for multiple methods." },
- { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, NULL, 0, eArgTypeRegularExpression,
+ { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression,
"Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." },
- { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
+ { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
"Set the breakpoint by function basename (C++ namespaces and arguments will be ignored). "
"Can be repeated multiple times to make one breakpoint for multiple symbols." },
- { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypeRegularExpression,
+ { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression,
"Set the breakpoint by specifying a regular expression which is matched against the source text in a source file or files "
"specified with the -f option. The -f option can be specified more than once. "
"If no source files are specified, uses the current \"default source file\"" },
- { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLanguage,
+ { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,
"Set the breakpoint on exceptions thrown by the specified language (without options, on throw but not catch.)" },
- { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
+ { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
"Set the breakpoint on exception throW." },
- { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
+ { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
"Set the breakpoint on exception catcH." },
- { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
+ { 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." },
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -1012,16 +1015,16 @@ private:
OptionDefinition
CommandObjectBreakpointModify::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
-{ LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
-{ LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument."},
-{ LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."},
-{ LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."},
-{ LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, NULL, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."},
-{ LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
-{ LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Enable the breakpoint."},
-{ LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Disable the breakpoint."},
-{ 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
+{ LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
+{ LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument."},
+{ LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."},
+{ LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."},
+{ LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."},
+{ 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."},
+{ 0, false, NULL, 0 , 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -1078,7 +1081,7 @@ protected:
{
// No breakpoint selected; enable all currently set breakpoints.
target->EnableAllBreakpoints ();
- result.AppendMessageWithFormat ("All breakpoints enabled. (%zu breakpoints)\n", num_breakpoints);
+ result.AppendMessageWithFormat ("All breakpoints enabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints);
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
@@ -1197,7 +1200,7 @@ protected:
{
// No breakpoint selected; disable all currently set breakpoints.
target->DisableAllBreakpoints ();
- result.AppendMessageWithFormat ("All breakpoints disabled. (%zu breakpoints)\n", num_breakpoints);
+ result.AppendMessageWithFormat ("All breakpoints disabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints);
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
@@ -1421,21 +1424,21 @@ private:
OptionDefinition
CommandObjectBreakpointList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Show debugger internal breakpoints" },
- { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Give a brief description of the breakpoint (no location info)."},
// FIXME: We need to add an "internal" command, and then add this sort of thing to it.
// But I need to see it for now, and don't want to wait.
- { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Give a full description of the breakpoint and its locations."},
- { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Explain everything we know about the breakpoint (for debugging debugger bugs)." },
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -1632,13 +1635,13 @@ private:
OptionDefinition
CommandObjectBreakpointClear::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
"Specify the breakpoint by source location in this particular file."},
- { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum,
+ { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
"Specify the breakpoint by source location at this particular line."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -1699,7 +1702,7 @@ protected:
else
{
target->RemoveAllBreakpoints ();
- result.AppendMessageWithFormat ("All breakpoints removed. (%zu %s)\n", num_breakpoints, num_breakpoints > 1 ? "breakpoints" : "breakpoint");
+ result.AppendMessageWithFormat ("All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
}
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
@@ -1843,7 +1846,7 @@ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *targe
if (breakpoint != NULL)
{
const size_t num_locations = breakpoint->GetNumLocations();
- if (cur_bp_id.GetLocationID() > num_locations)
+ if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations)
{
StreamString id_str;
BreakpointID::GetCanonicalReference (&id_str,
diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp
index 532d6cedc83e..fdb87d11900b 100644
--- a/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -44,9 +44,10 @@ public:
CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"add",
- "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
+ "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit."
+ " If no breakpoint is specified, adds the commands to the last created breakpoint.",
NULL),
- IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
+ IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
m_options (interpreter)
{
SetHelpLong (
@@ -193,7 +194,7 @@ one command per line.\n" );
// Define the first (and only) variant of this arg.
bp_id_arg.arg_type = eArgTypeBreakpointID;
- bp_id_arg.arg_repetition = eArgRepeatPlain;
+ bp_id_arg.arg_repetition = eArgRepeatOptional;
// There is only one variant this argument could be; put it into the argument entry.
arg.push_back (bp_id_arg);
@@ -228,9 +229,12 @@ one command per line.\n" );
{
io_handler.SetIsDone(true);
- BreakpointOptions *bp_options = (BreakpointOptions *) io_handler.GetUserData();
- if (bp_options)
+ std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
+ for (BreakpointOptions *bp_options : *bp_options_vec)
{
+ if (!bp_options)
+ continue;
+
std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
if (data_ap.get())
{
@@ -239,36 +243,37 @@ one command per line.\n" );
bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
}
}
-
}
void
- CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
+ CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
CommandReturnObject &result)
{
m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt
*this, // IOHandlerDelegate
true, // Run IOHandler in async mode
- bp_options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
+ &bp_options_vec); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
}
/// Set a one-liner as the callback for the breakpoint.
void
- SetBreakpointCommandCallback (BreakpointOptions *bp_options,
+ SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
const char *oneliner)
{
- std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
-
- // It's necessary to set both user_source and script_source to the oneliner.
- // The former is used to generate callback description (as in breakpoint command list)
- // while the latter is used for Python to interpret during the actual callback.
- data_ap->user_source.AppendString (oneliner);
- data_ap->script_source.assign (oneliner);
- data_ap->stop_on_error = m_options.m_stop_on_error;
+ for (auto bp_options : bp_options_vec)
+ {
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
- BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
- bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
+ // It's necessary to set both user_source and script_source to the oneliner.
+ // The former is used to generate callback description (as in breakpoint command list)
+ // while the latter is used for Python to interpret during the actual callback.
+ data_ap->user_source.AppendString (oneliner);
+ data_ap->script_source.assign (oneliner);
+ data_ap->stop_on_error = m_options.m_stop_on_error;
+ BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+ bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
+ }
return;
}
@@ -459,15 +464,11 @@ protected:
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+ m_bp_options_vec.clear();
+
if (result.Succeeded())
{
const size_t count = valid_bp_ids.GetSize();
- if (count > 1)
- {
- result.AppendError ("can only add commands to one breakpoint at a time.");
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
for (size_t i = 0; i < count; ++i)
{
@@ -489,50 +490,45 @@ protected:
if (bp_loc_sp)
bp_options = bp_loc_sp->GetLocationOptions();
}
+ if (bp_options)
+ m_bp_options_vec.push_back (bp_options);
+ }
+ }
- // Skip this breakpoint if bp_options is not good.
- if (bp_options == NULL) continue;
-
- // If we are using script language, get the script interpreter
- // in order to set or collect command callback. Otherwise, call
- // the methods associated with this object.
- if (m_options.m_use_script_language)
- {
- // Special handling for one-liner specified inline.
- if (m_options.m_use_one_liner)
- {
- m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
- m_options.m_one_liner.c_str());
- }
- // Special handling for using a Python function by name
- // instead of extending the breakpoint callback data structures, we just automatize
- // what the user would do manually: make their breakpoint command be a function call
- else if (m_options.m_function_name.size())
- {
- std::string oneliner("return ");
- oneliner += m_options.m_function_name;
- oneliner += "(frame, bp_loc, internal_dict)";
- m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
- oneliner.c_str());
- }
- else
- {
- m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
- result);
- }
- }
- else
- {
- // Special handling for one-liner specified inline.
- if (m_options.m_use_one_liner)
- SetBreakpointCommandCallback (bp_options,
- m_options.m_one_liner.c_str());
- else
- CollectDataForBreakpointCommandCallback (bp_options,
- result);
- }
+ // If we are using script language, get the script interpreter
+ // in order to set or collect command callback. Otherwise, call
+ // the methods associated with this object.
+ if (m_options.m_use_script_language)
+ {
+ ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter();
+ // Special handling for one-liner specified inline.
+ if (m_options.m_use_one_liner)
+ {
+ script_interp->SetBreakpointCommandCallback (m_bp_options_vec,
+ m_options.m_one_liner.c_str());
+ }
+ else if (m_options.m_function_name.size())
+ {
+ script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec,
+ m_options.m_function_name.c_str());
+ }
+ else
+ {
+ script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec,
+ result);
}
}
+ else
+ {
+ // Special handling for one-liner specified inline.
+ if (m_options.m_use_one_liner)
+ SetBreakpointCommandCallback (m_bp_options_vec,
+ m_options.m_one_liner.c_str());
+ else
+ CollectDataForBreakpointCommandCallback (m_bp_options_vec,
+ result);
+ }
+
}
return result.Succeeded();
@@ -540,6 +536,17 @@ protected:
private:
CommandOptions m_options;
+ std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the breakpoint options that we are currently
+ // collecting commands for. In the CollectData... calls we need
+ // to hand this off to the IOHandler, which may run asynchronously.
+ // So we have to have some way to keep it alive, and not leak it.
+ // Making it an ivar of the command object, which never goes away
+ // achieves this. Note that if we were able to run
+ // the same command concurrently in one interpreter we'd have to
+ // make this "per invocation". But there are many more reasons
+ // why it is not in general safe to do that in lldb at present,
+ // so it isn't worthwhile to come up with a more complex mechanism
+ // to address this particular weakness right now.
static const char *g_reader_instructions;
};
@@ -562,19 +569,19 @@ g_script_option_enumeration[4] =
OptionDefinition
CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOneLiner,
+ { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOneLiner,
"Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
- { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
+ { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
"Specify whether breakpoint command execution should terminate on error." },
- { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, g_script_option_enumeration, 0, eArgTypeNone,
+ { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, NULL, g_script_option_enumeration, 0, eArgTypeNone,
"Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
- { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, 0, eArgTypePythonFunction,
+ { 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."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -814,7 +821,7 @@ protected:
CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
CommandObjectMultiword (interpreter,
"command",
- "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
+ "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commands').",
"command <sub-command> [<sub-command-options>] <breakpoint-id>")
{
CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp
index 7bfdec094d6c..7d9bb7dad8fd 100644
--- a/source/Commands/CommandObjectCommands.cpp
+++ b/source/Commands/CommandObjectCommands.cpp
@@ -226,11 +226,11 @@ protected:
OptionDefinition
CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, "How many history commands to print."},
-{ LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)."},
-{ LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."},
-{ LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, NULL, 0, eArgTypeBoolean, "Clears the current command history."},
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger, "How many history commands to print."},
+{ LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)."},
+{ LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."},
+{ LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeBoolean, "Clears the current command history."},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -427,10 +427,10 @@ protected:
OptionDefinition
CommandObjectCommandsSource::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
-{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
-{ LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true don't echo commands while executing."},
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
+{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
+{ LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true don't echo commands while executing."},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#pragma mark CommandObjectCommandsAlias
@@ -889,7 +889,7 @@ public:
SetHelpLong(
"This command allows the user to create powerful regular expression commands\n"
"with substitutions. The regular expressions and substitutions are specified\n"
-"using the regular exression substitution format of:\n"
+"using the regular expression substitution format of:\n"
"\n"
" s/<regex>/<subst>/\n"
"\n"
@@ -1034,9 +1034,10 @@ protected:
Debugger &debugger = m_interpreter.GetDebugger();
const bool multiple_lines = true; // Get multiple lines
IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
- "lldb", // Name of input reader for history
- "\033[K> ", // Prompt and clear line
+ "lldb-regex", // Name of input reader for history
+ "\033[K> ", // Prompt and clear line
multiple_lines,
+ 0, // Don't show line numbers
*this));
if (io_handler_sp)
@@ -1273,9 +1274,9 @@ private:
OptionDefinition
CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone, "The help text to display for this command."},
-{ LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
-{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone, "The help text to display for this command."},
+{ LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
+{ 0 , false, NULL , 0 , 0 , NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -1547,8 +1548,8 @@ protected:
OptionDefinition
CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -1795,9 +1796,9 @@ static OptionEnumValueElement g_script_synchro_type[] =
OptionDefinition
CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."},
- { LLDB_OPT_SET_1, false, "synchronicity", 's', OptionParser::eRequiredArgument, 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, 0, eArgTypeNone, NULL }
+ { 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, "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 }
};
//-------------------------------------------------------------------------
diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp
index f9c683b364ce..8124ce1ef93b 100644
--- a/source/Commands/CommandObjectDisassemble.cpp
+++ b/source/Commands/CommandObjectDisassemble.cpp
@@ -232,29 +232,29 @@ CommandObjectDisassemble::CommandOptions::GetDefinitions ()
OptionDefinition
CommandObjectDisassemble::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "bytes" , 'b', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Show opcode bytes when disassembling."},
-{ LLDB_OPT_SET_ALL, false, "context" , 'C', OptionParser::eRequiredArgument , NULL, 0, eArgTypeNumLines, "Number of context lines of source to show."},
-{ LLDB_OPT_SET_ALL, false, "mixed" , 'm', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Enable mixed source and assembly display."},
-{ LLDB_OPT_SET_ALL, false, "raw" , 'r', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Print raw disassembly with no symbol information."},
-{ LLDB_OPT_SET_ALL, false, "plugin" , 'P', OptionParser::eRequiredArgument , NULL, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."},
-{ LLDB_OPT_SET_ALL, false, "flavor" , 'F', OptionParser::eRequiredArgument , NULL, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. "
- "Currently the only valid options are default, and for Intel"
- " architectures, att and intel."},
-{ LLDB_OPT_SET_ALL, false, "arch" , 'A', OptionParser::eRequiredArgument , NULL, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."},
+{ LLDB_OPT_SET_ALL, false, "bytes" , 'b', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Show opcode bytes when disassembling."},
+{ LLDB_OPT_SET_ALL, false, "context" , 'C', OptionParser::eRequiredArgument , NULL, NULL, 0, eArgTypeNumLines, "Number of context lines of source to show."},
+{ LLDB_OPT_SET_ALL, false, "mixed" , 'm', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Enable mixed source and assembly display."},
+{ LLDB_OPT_SET_ALL, false, "raw" , 'r', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Print raw disassembly with no symbol information."},
+{ LLDB_OPT_SET_ALL, false, "plugin" , 'P', OptionParser::eRequiredArgument , NULL, NULL, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."},
+{ LLDB_OPT_SET_ALL, false, "flavor" , 'F', OptionParser::eRequiredArgument , NULL, NULL, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. "
+ "Currently the only valid options are default, and for Intel"
+ " architectures, att and intel."},
+{ LLDB_OPT_SET_ALL, false, "arch" , 'A', OptionParser::eRequiredArgument , NULL, NULL, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."},
{ LLDB_OPT_SET_1 |
- LLDB_OPT_SET_2 , true , "start-address", 's', OptionParser::eRequiredArgument , NULL, 0, eArgTypeAddressOrExpression,"Address at which to start disassembling."},
-{ LLDB_OPT_SET_1 , false, "end-address" , 'e', OptionParser::eRequiredArgument , NULL, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling."},
+ LLDB_OPT_SET_2 , true , "start-address", 's', OptionParser::eRequiredArgument , NULL, NULL, 0, eArgTypeAddressOrExpression,"Address at which to start disassembling."},
+{ LLDB_OPT_SET_1 , false, "end-address" , 'e', OptionParser::eRequiredArgument , NULL, NULL, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling."},
{ LLDB_OPT_SET_2 |
LLDB_OPT_SET_3 |
LLDB_OPT_SET_4 |
- LLDB_OPT_SET_5 , false, "count" , 'c', OptionParser::eRequiredArgument , NULL, 0, eArgTypeNumLines, "Number of instructions to display."},
-{ LLDB_OPT_SET_3 , false, "name" , 'n', OptionParser::eRequiredArgument , NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
- "Disassemble entire contents of the given function name."},
-{ LLDB_OPT_SET_4 , false, "frame" , 'f', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."},
-{ LLDB_OPT_SET_5 , false, "pc" , 'p', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Disassemble around the current pc."},
-{ LLDB_OPT_SET_6 , false, "line" , 'l', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there is debug line table information, else disassemble around the pc."},
-{ LLDB_OPT_SET_7 , false, "address" , 'a', OptionParser::eRequiredArgument , NULL, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."},
-{ 0 , false, NULL , 0, 0 , NULL, 0, eArgTypeNone, NULL }
+ LLDB_OPT_SET_5 , false, "count" , 'c', OptionParser::eRequiredArgument , NULL, NULL, 0, eArgTypeNumLines, "Number of instructions to display."},
+{ LLDB_OPT_SET_3 , false, "name" , 'n', OptionParser::eRequiredArgument , NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
+ "Disassemble entire contents of the given function name."},
+{ LLDB_OPT_SET_4 , false, "frame" , 'f', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."},
+{ LLDB_OPT_SET_5 , false, "pc" , 'p', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Disassemble around the current pc."},
+{ LLDB_OPT_SET_6 , false, "line" , 'l', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there is debug line table information, else disassemble around the pc."},
+{ LLDB_OPT_SET_7 , false, "address" , 'a', OptionParser::eRequiredArgument , NULL, NULL, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."},
+{ 0 , false, NULL , 0, 0 , NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -370,6 +370,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
}
else
{
+ std::vector<AddressRange> ranges;
AddressRange range;
StackFrame *frame = m_exe_ctx.GetFramePtr();
if (m_options.frame_line)
@@ -425,6 +426,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
// Disassembling at the PC always disassembles some number of instructions (not the whole function).
m_options.num_instructions = DEFAULT_DISASM_NUM_INS;
}
+ ranges.push_back(range);
}
else
{
@@ -441,49 +443,75 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
}
range.SetByteSize (m_options.end_addr - m_options.start_addr);
}
+ ranges.push_back(range);
}
else
{
if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS
- && target
- && !target->GetSectionLoadList().IsEmpty())
+ && target)
{
- bool failed = false;
- Address symbol_containing_address;
- if (target->GetSectionLoadList().ResolveLoadAddress (m_options.symbol_containing_addr, symbol_containing_address))
+ if (!target->GetSectionLoadList().IsEmpty())
{
- ModuleSP module_sp (symbol_containing_address.GetModule());
- SymbolContext sc;
- bool resolve_tail_call_address = true; // PC can be one past the address range of the function.
- module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, sc,
- resolve_tail_call_address);
- if (sc.function || sc.symbol)
+ bool failed = false;
+ Address symbol_containing_address;
+ if (target->GetSectionLoadList().ResolveLoadAddress (m_options.symbol_containing_addr, symbol_containing_address))
{
- sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range);
+ ModuleSP module_sp (symbol_containing_address.GetModule());
+ SymbolContext sc;
+ bool resolve_tail_call_address = true; // PC can be one past the address range of the function.
+ module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, sc,
+ resolve_tail_call_address);
+ if (sc.function || sc.symbol)
+ {
+ sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range);
+ }
+ else
+ {
+ failed = true;
+ }
}
else
{
failed = true;
}
+ if (failed)
+ {
+ result.AppendErrorWithFormat ("Could not find function bounds for address 0x%" PRIx64 "\n", m_options.symbol_containing_addr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ ranges.push_back(range);
}
else
{
- failed = true;
- }
- if (failed)
- {
- result.AppendErrorWithFormat ("Could not find function bounds for address 0x%" PRIx64 "\n", m_options.symbol_containing_addr);
- result.SetStatus (eReturnStatusFailed);
- return false;
+ for (lldb::ModuleSP module_sp : target->GetImages().Modules())
+ {
+ lldb::addr_t file_addr = m_options.symbol_containing_addr;
+ Address file_address;
+ if (module_sp->ResolveFileAddress(file_addr, file_address))
+ {
+ SymbolContext sc;
+ bool resolve_tail_call_address = true; // PC can be one past the address range of the function.
+ module_sp->ResolveSymbolContextForAddress (file_address, eSymbolContextEverything, sc, resolve_tail_call_address);
+ if (sc.function || sc.symbol)
+ {
+ sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range);
+ ranges.push_back(range);
+ }
+ }
+ }
+
}
}
}
}
}
+ else
+ ranges.push_back(range);
if (m_options.num_instructions != 0)
{
- if (!range.GetBaseAddress().IsValid())
+ if (ranges.size() == 0)
{
// The default action is to disassemble the current frame function.
if (frame)
@@ -504,29 +532,38 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
return false;
}
}
-
- if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
- m_options.arch,
- plugin_name,
- flavor_string,
- m_exe_ctx,
- range.GetBaseAddress(),
- m_options.num_instructions,
- m_options.show_mixed ? m_options.num_lines_context : 0,
- options,
- result.GetOutputStream()))
- {
- result.SetStatus (eReturnStatusSuccessFinishResult);
- }
- else
+
+ bool print_sc_header = ranges.size() > 1;
+ for (AddressRange cur_range : ranges)
{
- result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr);
- result.SetStatus (eReturnStatusFailed);
+ if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
+ m_options.arch,
+ plugin_name,
+ flavor_string,
+ m_exe_ctx,
+ cur_range.GetBaseAddress(),
+ m_options.num_instructions,
+ m_options.show_mixed ? m_options.num_lines_context : 0,
+ options,
+ result.GetOutputStream()))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ if (m_options.start_addr != LLDB_INVALID_ADDRESS)
+ result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr);
+ else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS)
+ result.AppendErrorWithFormat ("Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n", m_options.symbol_containing_addr);
+ result.SetStatus (eReturnStatusFailed);
+ }
}
+ if (print_sc_header)
+ result.AppendMessage("\n");
}
else
{
- if (!range.GetBaseAddress().IsValid())
+ if (ranges.size() == 0)
{
// The default action is to disassemble the current frame function.
if (frame)
@@ -548,27 +585,35 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
result.SetStatus (eReturnStatusFailed);
return false;
}
+ ranges.push_back(range);
}
- if (range.GetByteSize() == 0)
- range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
-
- if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
- m_options.arch,
- plugin_name,
- flavor_string,
- m_exe_ctx,
- range,
- m_options.num_instructions,
- m_options.show_mixed ? m_options.num_lines_context : 0,
- options,
- result.GetOutputStream()))
+
+ bool print_sc_header = ranges.size() > 1;
+ for (AddressRange cur_range : ranges)
{
- result.SetStatus (eReturnStatusSuccessFinishResult);
- }
- else
- {
- result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr);
- result.SetStatus (eReturnStatusFailed);
+ if (cur_range.GetByteSize() == 0)
+ cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
+
+ if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
+ m_options.arch,
+ plugin_name,
+ flavor_string,
+ m_exe_ctx,
+ cur_range,
+ m_options.num_instructions,
+ m_options.show_mixed ? m_options.num_lines_context : 0,
+ options,
+ result.GetOutputStream()))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ if (print_sc_header)
+ result.AppendMessage("\n");
}
}
}
diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp
index c772a2e58912..079c62ddfdff 100644
--- a/source/Commands/CommandObjectExpression.cpp
+++ b/source/Commands/CommandObjectExpression.cpp
@@ -34,6 +34,7 @@
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
using namespace lldb;
@@ -59,19 +60,19 @@ static OptionEnumValueElement g_description_verbosity_type[] =
OptionDefinition
CommandObjectExpression::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."},
- { LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."},
+ { LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, NULL, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."},
};
uint32_t
CommandObjectExpression::CommandOptions::GetNumDefinitions ()
{
- return sizeof(g_option_table)/sizeof(OptionDefinition);
+ return llvm::array_lengthof(g_option_table);
}
Error
@@ -173,7 +174,7 @@ CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpret
}
else
{
- ignore_breakpoints = false;
+ ignore_breakpoints = true;
unwind_on_error = true;
}
@@ -205,7 +206,7 @@ CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interprete
{
SetHelpLong(
"Timeouts:\n\
- If the expression can be evaluated statically (without runnning code) then it will be.\n\
+ If the expression can be evaluated statically (without running code) then it will be.\n\
Otherwise, by default the expression will run on the current thread with a short timeout:\n\
currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted\n\
and resumed with all threads running. You can use the -a option to disable retrying on all\n\
@@ -217,6 +218,15 @@ User defined variables:\n\
your user defined variable is a $, then the variable's value will be available in future\n\
expressions, otherwise it will just be available in the current expression.\n\
\n\
+\n\
+Continuing evaluation after a breakpoint:\n\
+ If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once\n\
+ you are done with your investigation, you can either remove the expression execution frames\n\
+ from the stack with \"thread return -x\" or if you are still interested in the expression result\n\
+ you can issue the \"continue\" command and the expression evaluation will complete and the\n\
+ expression result will be available using the \"thread.completed-expression\" key in the thread\n\
+ format.\n\
+\n\
Examples: \n\
\n\
expr my_struct->a = my_array[3] \n\
@@ -277,8 +287,6 @@ CommandObjectExpression::EvaluateExpression
{
lldb::ValueObjectSP result_valobj_sp;
- ExecutionResults exe_results;
-
bool keep_in_memory = true;
EvaluateExpressionOptions options;
@@ -290,15 +298,19 @@ CommandObjectExpression::EvaluateExpression
options.SetTryAllThreads(m_command_options.try_all_threads);
options.SetDebug(m_command_options.debug);
+ // If there is any chance we are going to stop and want to see
+ // what went wrong with our expression, we should generate debug info
+ if (!m_command_options.ignore_breakpoints ||
+ !m_command_options.unwind_on_error)
+ options.SetGenerateDebugInfo(true);
+
if (m_command_options.timeout > 0)
options.SetTimeoutUsec(m_command_options.timeout);
else
options.SetTimeoutUsec(0);
-
- exe_results = target->EvaluateExpression (expr,
- exe_ctx.GetFramePtr(),
- result_valobj_sp,
- options);
+
+ target->EvaluateExpression(expr, exe_ctx.GetFramePtr(),
+ result_valobj_sp, options);
if (result_valobj_sp)
{
@@ -406,6 +418,30 @@ CommandObjectExpression::IOHandlerLinesUpdated (IOHandler &io_handler,
return LineStatus::Success;
}
+void
+CommandObjectExpression::GetMultilineExpression ()
+{
+ m_expr_lines.clear();
+ m_expr_line_count = 0;
+
+ Debugger &debugger = GetCommandInterpreter().GetDebugger();
+ const bool multiple_lines = true; // Get multiple lines
+ IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
+ "lldb-expr", // Name of input reader for history
+ NULL, // No prompt
+ multiple_lines,
+ 1, // Show line numbers starting at 1
+ *this));
+
+ StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile());
+ if (output_sp)
+ {
+ output_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
+ output_sp->Flush();
+ }
+ debugger.PushIOHandler(io_handler_sp);
+}
+
bool
CommandObjectExpression::DoExecute
(
@@ -419,24 +455,7 @@ CommandObjectExpression::DoExecute
if (command[0] == '\0')
{
- m_expr_lines.clear();
- m_expr_line_count = 0;
-
- Debugger &debugger = GetCommandInterpreter().GetDebugger();
- const bool multiple_lines = true; // Get multiple lines
- IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
- "lldb-expr", // Name of input reader for history
- NULL, // No prompt
- multiple_lines,
- *this));
-
- StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile());
- if (output_sp)
- {
- output_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
- output_sp->Flush();
- }
- debugger.PushIOHandler(io_handler_sp);
+ GetMultilineExpression ();
return result.Succeeded();
}
@@ -475,6 +494,13 @@ CommandObjectExpression::DoExecute
result.SetStatus (eReturnStatusFailed);
return false;
}
+
+ // No expression following options
+ if (expr == NULL || expr[0] == '\0')
+ {
+ GetMultilineExpression ();
+ return result.Succeeded();
+ }
}
}
diff --git a/source/Commands/CommandObjectExpression.h b/source/Commands/CommandObjectExpression.h
index c943f0e8023d..168140d7fe56 100644
--- a/source/Commands/CommandObjectExpression.h
+++ b/source/Commands/CommandObjectExpression.h
@@ -96,6 +96,9 @@ protected:
Stream *output_stream,
Stream *error_stream,
CommandReturnObject *result = NULL);
+
+ void
+ GetMultilineExpression ();
OptionGroupOptions m_option_group;
OptionGroupFormat m_format_options;
diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp
index 0ef973261508..ce540a5c3100 100644
--- a/source/Commands/CommandObjectFrame.cpp
+++ b/source/Commands/CommandObjectFrame.cpp
@@ -204,7 +204,7 @@ protected:
if (m_options.relative_frame_offset < 0)
{
- if (frame_idx >= -m_options.relative_frame_offset)
+ if (static_cast<int32_t>(frame_idx) >= -m_options.relative_frame_offset)
frame_idx += m_options.relative_frame_offset;
else
{
@@ -224,7 +224,7 @@ protected:
// I don't want "up 20" where "20" takes you past the top of the stack to produce
// an error, but rather to just go to the top. So I have to count the stack here...
const uint32_t num_frames = thread->GetStackFrameCount();
- if (num_frames - frame_idx > m_options.relative_frame_offset)
+ if (static_cast<int32_t>(num_frames - frame_idx) > m_options.relative_frame_offset)
frame_idx += m_options.relative_frame_offset;
else
{
@@ -291,8 +291,8 @@ protected:
OptionDefinition
CommandObjectFrameSelect::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."},
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#pragma mark CommandObjectFrameVariable
@@ -471,7 +471,7 @@ protected:
if (regex.GetErrorAsCString(regex_error, sizeof(regex_error)))
result.GetErrorStream().Printf ("error: %s\n", regex_error);
else
- result.GetErrorStream().Printf ("error: unkown regex error when compiling '%s'\n", name_cstr);
+ result.GetErrorStream().Printf ("error: unknown regex error when compiling '%s'\n", name_cstr);
}
}
else // No regex, either exact variable names or variable expressions.
diff --git a/source/Commands/CommandObjectHelp.cpp b/source/Commands/CommandObjectHelp.cpp
index bd0c3938c702..f73d9d23b574 100644
--- a/source/Commands/CommandObjectHelp.cpp
+++ b/source/Commands/CommandObjectHelp.cpp
@@ -54,9 +54,9 @@ CommandObjectHelp::~CommandObjectHelp()
OptionDefinition
CommandObjectHelp::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "show-aliases", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Show aliases in the command list."},
- { LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Hide user-defined commands from the list."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "show-aliases", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Show aliases in the command list."},
+ { LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Hide user-defined commands from the list."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
bool
diff --git a/source/Commands/CommandObjectLog.cpp b/source/Commands/CommandObjectLog.cpp
index 2d815846a607..7d32cc6d08a5 100644
--- a/source/Commands/CommandObjectLog.cpp
+++ b/source/Commands/CommandObjectLog.cpp
@@ -215,16 +215,16 @@ protected:
OptionDefinition
CommandObjectLogEnable::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Set the destination file to log to."},
-{ LLDB_OPT_SET_1, false, "threadsafe", 't', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines." },
-{ LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Enable verbose logging." },
-{ LLDB_OPT_SET_1, false, "debug", 'g', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Enable debug logging." },
-{ LLDB_OPT_SET_1, false, "sequence", 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Prepend all log lines with an increasing integer sequence id." },
-{ LLDB_OPT_SET_1, false, "timestamp", 'T', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Prepend all log lines with a timestamp." },
-{ LLDB_OPT_SET_1, false, "pid-tid", 'p', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Prepend all log lines with the process and thread ID that generates the log line." },
-{ LLDB_OPT_SET_1, false, "thread-name",'n', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Prepend all log lines with the thread name for the thread that generates the log line." },
-{ LLDB_OPT_SET_1, false, "stack", 'S', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Append a stack backtrace to each log line." },
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Set the destination file to log to."},
+{ LLDB_OPT_SET_1, false, "threadsafe", 't', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines." },
+{ LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Enable verbose logging." },
+{ LLDB_OPT_SET_1, false, "debug", 'g', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Enable debug logging." },
+{ LLDB_OPT_SET_1, false, "sequence", 's', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Prepend all log lines with an increasing integer sequence id." },
+{ LLDB_OPT_SET_1, false, "timestamp", 'T', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Prepend all log lines with a timestamp." },
+{ LLDB_OPT_SET_1, false, "pid-tid", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Prepend all log lines with the process and thread ID that generates the log line." },
+{ LLDB_OPT_SET_1, false, "thread-name",'n', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Prepend all log lines with the thread name for the thread that generates the log line." },
+{ LLDB_OPT_SET_1, false, "stack", 'S', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Append a stack backtrace to each log line." },
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
class CommandObjectLogDisable : public CommandObjectParsed
diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp
index cb7398fb9554..bfbb296158a9 100644
--- a/source/Commands/CommandObjectMemory.cpp
+++ b/source/Commands/CommandObjectMemory.cpp
@@ -42,12 +42,12 @@ using namespace lldb_private;
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
- { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."},
- { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
+ { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
+ { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."},
+ { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
{ LLDB_OPT_SET_1|
LLDB_OPT_SET_2|
- LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
+ LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
};
@@ -651,7 +651,7 @@ protected:
}
else if (m_format_options.GetCountValue().OptionWasSet())
{
- result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %zu), not both.\n", end_addr, item_count);
+ result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count);
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -685,7 +685,7 @@ protected:
data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
if (data_sp->GetBytes() == NULL)
{
- result.AppendErrorWithFormat ("can't allocate 0x%zx bytes for the memory read buffer, specify a smaller size to read", total_byte_size);
+ result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size);
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -708,7 +708,7 @@ protected:
}
if (bytes_read < total_byte_size)
- result.AppendWarningWithFormat("Not all bytes (%zu/%zu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr);
+ result.AppendWarningWithFormat("Not all bytes (%" PRIu64 "/%" PRIu64 ") were able to be read from 0x%" PRIx64 ".\n", (uint64_t)bytes_read, (uint64_t)total_byte_size, addr);
}
else
{
@@ -878,7 +878,7 @@ protected:
// here we passed a count, and it was not 1
// so we have a byte_size and a count
// we could well multiply those, but instead let's just fail
- result.AppendErrorWithFormat("reading memory as characters of size %zu is not supported", item_byte_size);
+ result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -917,10 +917,10 @@ protected:
OptionDefinition
g_memory_find_option_table[] =
{
- { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
- { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
- { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "How many times to perform the search."},
- { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "dump-offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."},
+ { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
+ { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
+ { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many times to perform the search."},
+ { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "dump-offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."},
};
//----------------------------------------------------------------------
@@ -1223,8 +1223,8 @@ protected:
OptionDefinition
g_memory_write_option_table[] =
{
-{ LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
-{ LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
+{ LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
+{ LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."},
};
//----------------------------------------------------------------------
@@ -1536,7 +1536,7 @@ protected:
}
else if (!UIntValueIsValidForSize (uval64, item_byte_size))
{
- result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size);
+ result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1564,7 +1564,7 @@ protected:
}
else if (!UIntValueIsValidForSize (uval64, item_byte_size))
{
- result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size);
+ result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1604,7 +1604,7 @@ protected:
}
else if (!SIntValueIsValidForSize (sval64, item_byte_size))
{
- result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %zu byte signed integer value.\n", sval64, item_byte_size);
+ result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %" PRIu64 " byte signed integer value.\n", sval64, (uint64_t)item_byte_size);
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1621,7 +1621,7 @@ protected:
}
else if (!UIntValueIsValidForSize (uval64, item_byte_size))
{
- result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size);
+ result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1638,7 +1638,7 @@ protected:
}
else if (!UIntValueIsValidForSize (uval64, item_byte_size))
{
- result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size);
+ result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
result.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp
index 5e842bf848a3..9998dbdccdad 100644
--- a/source/Commands/CommandObjectPlatform.cpp
+++ b/source/Commands/CommandObjectPlatform.cpp
@@ -21,6 +21,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandOptionValidators.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFile.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"
@@ -64,20 +65,19 @@ ParsePermissionString(const char* permissions)
static OptionDefinition
g_permissions_options[] =
{
- { LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, NULL, 0, eArgTypePermissionsNumber , "Give out the numeric value for permissions (e.g. 757)" },
- { LLDB_OPT_SET_ALL, false, "permissions-string",'s', OptionParser::eRequiredArgument, NULL, 0, eArgTypePermissionsString , "Give out the string value for permissions (e.g. rwxr-xr--)." },
- { LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow user to read." },
- { LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow user to write." },
- { LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow user to execute." },
-
- { LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow group to read." },
- { LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow group to write." },
- { LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow group to execute." },
-
- { LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow world to read." },
- { LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow world to write." },
- { LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow world to execute." },
-
+ { LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePermissionsNumber , "Give out the numeric value for permissions (e.g. 757)" },
+ { LLDB_OPT_SET_ALL, false, "permissions-string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePermissionsString , "Give out the string value for permissions (e.g. rwxr-xr--)." },
+ { LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow user to read." },
+ { LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow user to write." },
+ { LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow user to execute." },
+
+ { LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow group to read." },
+ { LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow group to write." },
+ { LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow group to execute." },
+
+ { LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow world to read." },
+ { LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow world to write." },
+ { LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow world to execute." },
};
class OptionPermissions : public lldb_private::OptionGroup
@@ -894,9 +894,9 @@ protected:
OptionDefinition
CommandObjectPlatformFRead::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "offset" , 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeIndex , "Offset into the file at which to start reading." },
- { LLDB_OPT_SET_1, false, "count" , 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount , "Number of bytes to read from the file." },
- { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
+ { LLDB_OPT_SET_1, false, "offset" , 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex , "Offset into the file at which to start reading." },
+ { LLDB_OPT_SET_1, false, "count" , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount , "Number of bytes to read from the file." },
+ { 0 , false, NULL , 0 , 0 , NULL, NULL, 0, eArgTypeNone , NULL }
};
@@ -1020,9 +1020,9 @@ protected:
OptionDefinition
CommandObjectPlatformFWrite::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "offset" , 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeIndex , "Offset into the file at which to start reading." },
- { LLDB_OPT_SET_1, false, "data" , 'd', OptionParser::eRequiredArgument, NULL, 0, eArgTypeValue , "Text to write to the file." },
- { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
+ { LLDB_OPT_SET_1, false, "offset" , 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex , "Offset into the file at which to start reading." },
+ { LLDB_OPT_SET_1, false, "data" , 'd', OptionParser::eRequiredArgument , NULL, NULL, 0, eArgTypeValue , "Text to write to the file." },
+ { 0 , false, NULL , 0 , 0 , NULL, NULL, 0, eArgTypeNone , NULL }
};
class CommandObjectPlatformFile : public CommandObjectMultiword
@@ -1645,24 +1645,29 @@ protected:
CommandOptions m_options;
};
+namespace
+{
+ PosixPlatformCommandOptionValidator g_posix_validator;
+}
+
OptionDefinition
CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1 , false, "pid" , 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePid , "List the process info for a specific process ID." },
-{ LLDB_OPT_SET_2 , true , "name" , 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." },
-{ LLDB_OPT_SET_3 , true , "ends-with" , 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that end with a string." },
-{ LLDB_OPT_SET_4 , true , "starts-with", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that start with a string." },
-{ LLDB_OPT_SET_5 , true , "contains" , 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that contain a string." },
-{ LLDB_OPT_SET_6 , true , "regex" , 'r', OptionParser::eRequiredArgument, NULL, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "parent" , 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "uid" , 'u', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching user ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "euid" , 'U', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching effective user ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "gid" , 'g', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching group ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "egid" , 'G', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching effective group ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "arch" , 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." },
-{ LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args" , 'A', OptionParser::eNoArgument , NULL, 0, eArgTypeNone , "Show process arguments instead of the process executable basename." },
-{ LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose" , 'v', OptionParser::eNoArgument , NULL, 0, eArgTypeNone , "Enable verbose output." },
-{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
+{ LLDB_OPT_SET_1 , false, "pid" , 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid , "List the process info for a specific process ID." },
+{ LLDB_OPT_SET_2 , true , "name" , 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." },
+{ LLDB_OPT_SET_3 , true , "ends-with" , 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that end with a string." },
+{ LLDB_OPT_SET_4 , true , "starts-with", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that start with a string." },
+{ LLDB_OPT_SET_5 , true , "contains" , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that contain a string." },
+{ LLDB_OPT_SET_6 , true , "regex" , 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "parent" , 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "uid" , 'u', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching user ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "euid" , 'U', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching effective user ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "gid" , 'g', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching group ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "egid" , 'G', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching effective group ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "arch" , 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." },
+{ LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args" , 'A', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone , "Show process arguments instead of the process executable basename." },
+{ LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose" , 'v', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone , "Enable verbose output." },
+{ 0 , false, NULL , 0 , 0 , NULL, NULL, 0, eArgTypeNone , NULL }
};
//----------------------------------------------------------------------
@@ -1965,11 +1970,11 @@ protected:
OptionDefinition
CommandObjectPlatformProcessAttach::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
- { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
- { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
- { LLDB_OPT_SET_2, false, "waitfor",'w', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "plugin", 'P' , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
+ { LLDB_OPT_SET_1, false, "pid", 'p' , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
+ { LLDB_OPT_SET_2, false, "name", 'n' , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
+ { LLDB_OPT_SET_2, false, "waitfor", 'w' , OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."},
+ { 0, false, NULL , 0 , 0 , NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -2192,8 +2197,8 @@ public:
OptionDefinition
CommandObjectPlatformShell::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp
index 49a392286c6a..6536c6ef1693 100644
--- a/source/Commands/CommandObjectProcess.cpp
+++ b/source/Commands/CommandObjectProcess.cpp
@@ -20,6 +20,7 @@
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/Options.h"
@@ -204,8 +205,28 @@ protected:
const char *target_settings_argv0 = target->GetArg0();
- if (target->GetDisableASLR())
+ // Determine whether we will disable ASLR or leave it in the default state (i.e. enabled if the platform supports it).
+ // First check if the process launch options explicitly turn on/off disabling ASLR. If so, use that setting;
+ // otherwise, use the 'settings target.disable-aslr' setting.
+ bool disable_aslr = false;
+ if (m_options.disable_aslr != eLazyBoolCalculate)
+ {
+ // The user specified an explicit setting on the process launch line. Use it.
+ disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
+ }
+ else
+ {
+ // The user did not explicitly specify whether to disable ASLR. Fall back to the target.disable-aslr setting.
+ disable_aslr = target->GetDisableASLR ();
+ }
+
+ if (disable_aslr)
m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
+ else
+ m_options.launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
+
+ if (target->GetDetachOnError())
+ m_options.launch_info.GetFlags().Set (eLaunchFlagDetachOnError);
if (target->GetDisableSTDIO())
m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
@@ -532,6 +553,9 @@ protected:
if (error.Success())
{
+ // Update the execution context so the current target and process are now selected
+ // in case we interrupt
+ m_interpreter.UpdateExecutionContext(NULL);
ListenerSP listener_sp (new Listener("lldb.CommandObjectProcessAttach.DoExecute.attach.hijack"));
m_options.attach_info.SetHijackListener(listener_sp);
process->HijackProcessEvents(listener_sp.get());
@@ -553,7 +577,11 @@ protected:
}
else
{
- result.AppendError ("attach failed: process did not stop (no such process or permission problem?)");
+ const char *exit_desc = process->GetExitDescription();
+ if (exit_desc)
+ result.AppendErrorWithFormat ("attach failed: %s", exit_desc);
+ else
+ result.AppendError ("attach failed: process did not stop (no such process or permission problem?)");
process->Destroy();
result.SetStatus (eReturnStatusFailed);
}
@@ -617,13 +645,13 @@ protected:
OptionDefinition
CommandObjectProcessAttach::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "continue",'c', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Immediately continue the process once attached."},
-{ LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
-{ LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
-{ LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
-{ LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Include existing processes when doing attach -w."},
-{ LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Wait for the process with <process-name> to launch."},
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_ALL, false, "continue",'c', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Immediately continue the process once attached."},
+{ LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
+{ LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
+{ LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
+{ LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Include existing processes when doing attach -w."},
+{ LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Wait for the process with <process-name> to launch."},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -758,13 +786,20 @@ protected:
// Set the actions that the threads should each take when resuming
for (uint32_t idx=0; idx<num_threads; ++idx)
{
- process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
+ const bool override_suspend = false;
+ process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning, override_suspend);
}
}
-
+
Error error(process->Resume());
+
if (error.Success())
{
+ // 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
+ // a chance to call PushProcessIOHandler().
+ process->SyncIOHandler(2000);
+
result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
if (synchronous_execution)
{
@@ -807,9 +842,9 @@ protected:
OptionDefinition
CommandObjectProcessContinue::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger,
+{ LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger,
"Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread."},
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -911,7 +946,6 @@ protected:
DoExecute (Args& command, CommandReturnObject &result)
{
Process *process = m_exe_ctx.GetProcessPtr();
- result.AppendMessageWithFormat ("Detaching from process %" PRIu64 "\n", process->GetID());
// FIXME: This will be a Command Option:
bool keep_stopped;
if (m_options.m_keep_stopped == eLazyBoolCalculate)
@@ -947,8 +981,8 @@ protected:
OptionDefinition
CommandObjectProcessDetach::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." },
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." },
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -1119,8 +1153,8 @@ protected:
OptionDefinition
CommandObjectProcessConnect::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
- { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
+ { 0, false, NULL, 0 , 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -1483,6 +1517,71 @@ protected:
};
//-------------------------------------------------------------------------
+// CommandObjectProcessSaveCore
+//-------------------------------------------------------------------------
+#pragma mark CommandObjectProcessSaveCore
+
+class CommandObjectProcessSaveCore : public CommandObjectParsed
+{
+public:
+
+ CommandObjectProcessSaveCore (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "process save-core",
+ "Save the current process as a core file using an appropriate file type.",
+ "process save-core FILE",
+ eFlagRequiresProcess |
+ eFlagTryTargetAPILock |
+ eFlagProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectProcessSaveCore ()
+ {
+ }
+
+protected:
+ bool
+ DoExecute (Args& command,
+ CommandReturnObject &result)
+ {
+ ProcessSP process_sp = m_exe_ctx.GetProcessSP();
+ if (process_sp)
+ {
+ if (command.GetArgumentCount() == 1)
+ {
+ FileSpec output_file(command.GetArgumentAtIndex(0), false);
+ Error error = PluginManager::SaveCore(process_sp, output_file);
+ if (error.Success())
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Failed to save core file for process: %s\n", error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("'%s' takes one arguments:\nUsage: %s\n",
+ m_cmd_name.c_str(),
+ m_cmd_syntax.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("invalid process");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ return result.Succeeded();
+ }
+};
+
+//-------------------------------------------------------------------------
// CommandObjectProcessStatus
//-------------------------------------------------------------------------
#pragma mark CommandObjectProcessStatus
@@ -1824,10 +1923,10 @@ protected:
OptionDefinition
CommandObjectProcessHandle::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
-{ LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." },
-{ LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
+{ LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." },
+{ LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -1853,6 +1952,7 @@ CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter
LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter)));
LoadSubCommand ("plugin", CommandObjectSP (new CommandObjectProcessPlugin (interpreter)));
+ LoadSubCommand ("save-core", CommandObjectSP (new CommandObjectProcessSaveCore (interpreter)));
}
CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
diff --git a/source/Commands/CommandObjectQuit.cpp b/source/Commands/CommandObjectQuit.cpp
index ffe2a9240726..dd0efc61b2d0 100644
--- a/source/Commands/CommandObjectQuit.cpp
+++ b/source/Commands/CommandObjectQuit.cpp
@@ -53,7 +53,7 @@ CommandObjectQuit::ShouldAskForConfirmation (bool& is_a_detach)
continue;
const TargetList& target_list(debugger_sp->GetTargetList());
for (uint32_t target_idx = 0;
- target_idx < target_list.GetNumTargets();
+ target_idx < static_cast<uint32_t>(target_list.GetNumTargets());
target_idx++)
{
TargetSP target_sp(target_list.GetTargetAtIndex(target_idx));
diff --git a/source/Commands/CommandObjectRegister.cpp b/source/Commands/CommandObjectRegister.cpp
index deaf2ab3793e..81b79b8cd8b2 100644
--- a/source/Commands/CommandObjectRegister.cpp
+++ b/source/Commands/CommandObjectRegister.cpp
@@ -31,6 +31,7 @@
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Thread.h"
+#include "llvm/ADT/STLExtras.h"
using namespace lldb;
using namespace lldb_private;
@@ -202,7 +203,7 @@ protected:
}
else
{
- result.AppendErrorWithFormat ("invalid register set index: %zu\n", set_idx);
+ result.AppendErrorWithFormat("invalid register set index: %" PRIu64 "\n", (uint64_t)set_idx);
result.SetStatus (eReturnStatusFailed);
break;
}
@@ -352,15 +353,15 @@ protected:
const OptionDefinition
CommandObjectRegisterRead::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument , NULL, 0, eArgTypeNone , "Display register names using the alternate register name if there is one."},
- { LLDB_OPT_SET_1 , false, "set" , 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeIndex , "Specify which register sets to dump by index."},
- { LLDB_OPT_SET_2 , false, "all" , 'a', OptionParser::eNoArgument , NULL, 0, eArgTypeNone , "Show all register sets."},
+ { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone , "Display register names using the alternate register name if there is one."},
+ { LLDB_OPT_SET_1 , false, "set" , 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex , "Specify which register sets to dump by index."},
+ { LLDB_OPT_SET_2 , false, "all" , 'a', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone , "Show all register sets."},
};
uint32_t
CommandObjectRegisterRead::CommandOptions::GetNumDefinitions ()
{
- return sizeof(g_option_table)/sizeof(OptionDefinition);
+ return llvm::array_lengthof(g_option_table);
}
diff --git a/source/Commands/CommandObjectSettings.cpp b/source/Commands/CommandObjectSettings.cpp
index 78a5ad6ca86a..ed677afabcb5 100644
--- a/source/Commands/CommandObjectSettings.cpp
+++ b/source/Commands/CommandObjectSettings.cpp
@@ -164,7 +164,8 @@ insert-before or insert-after.\n");
const size_t argc = input.GetArgumentCount();
const char *arg = NULL;
int setting_var_idx;
- for (setting_var_idx = 1; setting_var_idx < argc; ++setting_var_idx)
+ for (setting_var_idx = 1; setting_var_idx < static_cast<int>(argc);
+ ++setting_var_idx)
{
arg = input.GetArgumentAtIndex(setting_var_idx);
if (arg && arg[0] != '-')
@@ -288,8 +289,8 @@ private:
OptionDefinition
CommandObjectSettingsSet::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Apply the new value to the global default value." },
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Apply the new value to the global default value." },
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -1154,7 +1155,7 @@ protected:
if (argc != 1)
{
- result.AppendError ("'setttings clear' takes exactly one argument");
+ result.AppendError ("'settings clear' takes exactly one argument");
result.SetStatus (eReturnStatusFailed);
return false;
}
diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp
index bf2a42e0bea0..6b1b6aacc857 100644
--- a/source/Commands/CommandObjectSource.cpp
+++ b/source/Commands/CommandObjectSource.cpp
@@ -138,9 +138,9 @@ protected:
OptionDefinition
CommandObjectSourceInfo::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum, "The line number at which to start the display source."},
-{ LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source."},
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum, "The line number at which to start the display source."},
+{ LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source."},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#pragma mark CommandObjectSourceList
@@ -804,7 +804,7 @@ protected:
result.SetStatus (eReturnStatusFailed);
return false;
}
-
+
if (num_matches > 1)
{
bool got_multiple = false;
@@ -820,7 +820,7 @@ protected:
{
if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit))
got_multiple = true;
- break;
+ break;
}
else
test_cu_spec = sc.comp_unit;
@@ -828,7 +828,7 @@ protected:
}
if (got_multiple)
{
- result.AppendErrorWithFormat("Multiple source files found matching: \"%s.\"\n",
+ result.AppendErrorWithFormat("Multiple source files found matching: \"%s.\"\n",
m_options.file_name.c_str());
result.SetStatus (eReturnStatusFailed);
return false;
@@ -891,16 +891,16 @@ protected:
OptionDefinition
CommandObjectSourceList::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "The number of source lines to display."},
+{ LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "The number of source lines to display."},
{ LLDB_OPT_SET_1 |
- LLDB_OPT_SET_2 , false, "shlib", 's', OptionParser::eRequiredArgument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source file in the given shared library."},
-{ LLDB_OPT_SET_ALL, false, "show-breakpoints", 'b', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Show the line table locations from the debug information that indicate valid places to set source level breakpoints."},
-{ LLDB_OPT_SET_1 , false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source."},
-{ LLDB_OPT_SET_1 , false, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum, "The line number at which to start the display source."},
-{ LLDB_OPT_SET_2 , false, "name", 'n', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display."},
-{ LLDB_OPT_SET_3 , false, "address",'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line."},
-{ LLDB_OPT_SET_4, false, "reverse", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Reverse the listing to look backwards from the last displayed block of source."},
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ LLDB_OPT_SET_2 , false, "shlib", 's', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source file in the given shared library."},
+{ LLDB_OPT_SET_ALL, false, "show-breakpoints", 'b', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Show the line table locations from the debug information that indicate valid places to set source level breakpoints."},
+{ LLDB_OPT_SET_1 , false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source."},
+{ LLDB_OPT_SET_1 , false, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum, "The line number at which to start the display source."},
+{ LLDB_OPT_SET_2 , false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display."},
+{ LLDB_OPT_SET_3 , false, "address",'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line."},
+{ LLDB_OPT_SET_4, false, "reverse", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Reverse the listing to look backwards from the last displayed block of source."},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#pragma mark CommandObjectMultiwordSource
diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp
index 308b72f355d3..024f7b5a0415 100644
--- a/source/Commands/CommandObjectTarget.cpp
+++ b/source/Commands/CommandObjectTarget.cpp
@@ -63,18 +63,18 @@ static void
DumpTargetInfo (uint32_t target_idx, Target *target, const char *prefix_cstr, bool show_stopped_process_status, Stream &strm)
{
const ArchSpec &target_arch = target->GetArchitecture();
-
+
Module *exe_module = target->GetExecutableModulePointer();
char exe_path[PATH_MAX];
bool exe_valid = false;
if (exe_module)
exe_valid = exe_module->GetFileSpec().GetPath (exe_path, sizeof(exe_path));
-
+
if (!exe_valid)
::strcpy (exe_path, "<none>");
-
+
strm.Printf ("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx, exe_path);
-
+
uint32_t properties = 0;
if (target_arch.IsValid())
{
@@ -84,7 +84,7 @@ DumpTargetInfo (uint32_t target_idx, Target *target, const char *prefix_cstr, bo
PlatformSP platform_sp (target->GetPlatform());
if (platform_sp)
strm.Printf ("%splatform=%s", properties++ > 0 ? ", " : " ( ", platform_sp->GetName().GetCString());
-
+
ProcessSP process_sp (target->GetProcessSP());
bool show_process_status = false;
if (process_sp)
@@ -123,7 +123,7 @@ DumpTargetList (TargetList &target_list, bool show_stopped_process_status, Strea
{
const uint32_t num_targets = target_list.GetNumTargets();
if (num_targets)
- {
+ {
TargetSP selected_target_sp (target_list.GetSelectedTarget());
strm.PutCString ("Current targets:\n");
for (uint32_t i=0; i<num_targets; ++i)
@@ -167,17 +167,17 @@ public:
{
CommandArgumentEntry arg;
CommandArgumentData file_arg;
-
+
// Define the first (and only) variant of this arg.
file_arg.arg_type = eArgTypeFilename;
file_arg.arg_repetition = eArgRepeatPlain;
-
+
// There is only one variant this argument could be; put it into the argument entry.
arg.push_back (file_arg);
-
+
// Push the data for the first argument into the m_arguments vector.
m_arguments.push_back (arg);
-
+
m_option_group.Append (&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Append (&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
@@ -210,7 +210,7 @@ public:
{
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
-
+
CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
CommandCompletions::eDiskFileCompletion,
completion_str.c_str(),
@@ -230,12 +230,38 @@ protected:
FileSpec core_file (m_core_file.GetOptionValue().GetCurrentValue());
FileSpec remote_file (m_remote_file.GetOptionValue().GetCurrentValue());
+ if (core_file)
+ {
+ if (!core_file.Exists())
+ {
+ result.AppendErrorWithFormat("core file '%s' doesn't exist", core_file.GetPath().c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+
+ }
+ if (!core_file.Readable())
+ {
+ result.AppendErrorWithFormat("core file '%s' is not readable", core_file.GetPath().c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+
if (argc == 1 || core_file || remote_file)
{
FileSpec symfile (m_symbol_file.GetOptionValue().GetCurrentValue());
if (symfile)
{
- if (!symfile.Exists())
+ if (symfile.Exists())
+ {
+ if (!symfile.Readable())
+ {
+ result.AppendErrorWithFormat("symbol file '%s' is not readable", core_file.GetPath().c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
{
char symfile_path[PATH_MAX];
symfile.GetPath(symfile_path, sizeof(symfile_path));
@@ -248,12 +274,12 @@ protected:
const char *file_path = command.GetArgumentAtIndex(0);
Timer scoped_timer(__PRETTY_FUNCTION__, "(lldb) target create '%s'", file_path);
FileSpec file_spec;
-
+
if (file_path)
file_spec.SetFile (file_path, true);
-
+
bool must_set_platform_path = false;
-
+
Debugger &debugger = m_interpreter.GetDebugger();
PlatformSP platform_sp(debugger.GetPlatformList().GetSelectedPlatform ());
@@ -334,7 +360,7 @@ protected:
}
}
}
-
+
debugger.GetTargetList().SetSelectedTarget(target_sp.get());
if (must_set_platform_path)
{
@@ -352,7 +378,7 @@ protected:
FileSpec core_file_dir;
core_file_dir.GetDirectory() = core_file.GetDirectory();
target_sp->GetExecutableSearchPaths ().Append (core_file_dir);
-
+
ProcessSP process_sp (target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), NULL, &core_file));
if (process_sp)
@@ -360,7 +386,7 @@ protected:
// Seems wierd that we Launch a core file, but that is
// what we do!
error = process_sp->LoadCore();
-
+
if (error.Fail())
{
result.AppendError(error.AsCString("can't find plug-in for core file"));
@@ -403,7 +429,6 @@ protected:
result.SetStatus (eReturnStatusFailed);
}
return result.Succeeded();
-
}
private:
@@ -434,12 +459,12 @@ public:
0)
{
}
-
+
virtual
~CommandObjectTargetList ()
{
}
-
+
protected:
virtual bool
DoExecute (Args& args, CommandReturnObject &result)
@@ -447,7 +472,7 @@ protected:
if (args.GetArgumentCount() == 0)
{
Stream &strm = result.GetOutputStream();
-
+
bool show_stopped_process_status = false;
if (DumpTargetList (m_interpreter.GetDebugger().GetTargetList(), show_stopped_process_status, strm) == 0)
{
@@ -482,12 +507,12 @@ public:
0)
{
}
-
+
virtual
~CommandObjectTargetSelect ()
{
}
-
+
protected:
virtual bool
DoExecute (Args& args, CommandReturnObject &result)
@@ -520,9 +545,16 @@ protected:
}
else
{
- result.AppendErrorWithFormat ("index %u is out of range, valid target indexes are 0 - %u\n",
- target_idx,
- num_targets - 1);
+ if (num_targets > 0)
+ {
+ result.AppendErrorWithFormat ("index %u is out of range, valid target indexes are 0 - %u\n",
+ target_idx,
+ num_targets - 1);
+ } else
+ {
+ result.AppendErrorWithFormat ("index %u is out of range since there are no active targets\n",
+ target_idx);
+ }
result.SetStatus (eReturnStatusFailed);
}
}
@@ -562,12 +594,12 @@ public:
m_option_group.Append (&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Finalize();
}
-
+
virtual
~CommandObjectTargetDelete ()
{
}
-
+
Options *
GetOptions ()
{
@@ -600,7 +632,7 @@ protected:
if (success)
{
if (target_idx < num_targets)
- {
+ {
target_sp = target_list.GetTargetAtIndex (target_idx);
if (target_sp)
{
@@ -626,7 +658,6 @@ protected:
success = false;
}
}
-
}
else
{
@@ -661,10 +692,10 @@ protected:
result.GetOutputStream().Printf("%u targets deleted.\n", (uint32_t)num_targets_to_delete);
result.SetStatus(eReturnStatusSuccessFinishResult);
}
-
+
return result.Succeeded();
}
-
+
OptionGroupOptions m_option_group;
OptionGroupBoolean m_cleanup_option;
};
@@ -678,6 +709,9 @@ protected:
class CommandObjectTargetVariable : public CommandObjectParsed
{
+ static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file'
+ static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb'
+
public:
CommandObjectTargetVariable (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
@@ -688,23 +722,27 @@ public:
m_option_group (interpreter),
m_option_variable (false), // Don't include frame options
m_option_format (eFormatDefault),
- m_option_compile_units (LLDB_OPT_SET_1, false, "file", 'file', 0, eArgTypeFilename, "A basename or fullpath to a file that contains global variables. This option can be specified multiple times."),
- m_option_shared_libraries (LLDB_OPT_SET_1, false, "shlib",'shlb', 0, eArgTypeFilename, "A basename or fullpath to a shared library to use in the search for global variables. This option can be specified multiple times."),
+ m_option_compile_units (LLDB_OPT_SET_1, false, "file",
+ SHORT_OPTION_FILE, 0, eArgTypeFilename,
+ "A basename or fullpath to a file that contains global variables. This option can be specified multiple times."),
+ m_option_shared_libraries (LLDB_OPT_SET_1, false, "shlib",
+ SHORT_OPTION_SHLB, 0, eArgTypeFilename,
+ "A basename or fullpath to a shared library to use in the search for global variables. This option can be specified multiple times."),
m_varobj_options()
{
CommandArgumentEntry arg;
CommandArgumentData var_name_arg;
-
+
// Define the first (and only) variant of this arg.
var_name_arg.arg_type = eArgTypeVarName;
var_name_arg.arg_repetition = eArgRepeatPlus;
-
+
// There is only one variant this argument could be; put it into the argument entry.
arg.push_back (var_name_arg);
-
+
// Push the data for the first argument into the m_arguments vector.
m_arguments.push_back (arg);
-
+
m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Append (&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Append (&m_option_format, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1);
@@ -712,7 +750,7 @@ public:
m_option_group.Append (&m_option_shared_libraries, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Finalize();
}
-
+
virtual
~CommandObjectTargetVariable ()
{
@@ -722,33 +760,33 @@ public:
DumpValueObject (Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp, const char *root_name)
{
DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions());
-
+
switch (var_sp->GetScope())
{
case eValueTypeVariableGlobal:
if (m_option_variable.show_scope)
s.PutCString("GLOBAL: ");
break;
-
+
case eValueTypeVariableStatic:
if (m_option_variable.show_scope)
s.PutCString("STATIC: ");
break;
-
+
case eValueTypeVariableArgument:
if (m_option_variable.show_scope)
s.PutCString(" ARG: ");
break;
-
+
case eValueTypeVariableLocal:
if (m_option_variable.show_scope)
s.PutCString(" LOCAL: ");
break;
-
+
default:
break;
}
-
+
if (m_option_variable.show_decl)
{
bool show_fullpaths = false;
@@ -756,17 +794,16 @@ public:
if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
s.PutCString (": ");
}
-
+
const Format format = m_option_format.GetFormat();
if (format != eFormatDefault)
options.SetFormat(format);
options.SetRootValueObjectName(root_name);
-
+
valobj_sp->Dump(s,options);
}
-
-
+
static size_t GetVariableCallback (void *baton,
const char *name,
VariableList &variable_list)
@@ -781,17 +818,14 @@ public:
}
return 0;
}
-
-
Options *
GetOptions ()
{
return &m_option_group;
}
-
+
protected:
-
void
DumpGlobalVariableList(const ExecutionContext &exe_ctx, const SymbolContext &sc, const VariableList &variable_list, Stream &s)
{
@@ -817,14 +851,14 @@ protected:
s.Printf ("Global variables for %s\n",
sc.comp_unit->GetPath().c_str());
}
-
+
for (uint32_t i=0; i<count; ++i)
{
VariableSP var_sp (variable_list.GetVariableAtIndex(i));
if (var_sp)
{
ValueObjectSP valobj_sp (ValueObjectVariable::Create (exe_ctx.GetBestExecutionContextScope(), var_sp));
-
+
if (valobj_sp)
DumpValueObject (s, var_sp, valobj_sp, var_sp->GetName().GetCString());
}
@@ -838,7 +872,7 @@ protected:
Target *target = m_exe_ctx.GetTargetPtr();
const size_t argc = args.GetArgumentCount();
Stream &s = result.GetOutputStream();
-
+
if (argc > 0)
{
@@ -875,7 +909,7 @@ protected:
valobj_list));
matches = variable_list.GetSize();
}
-
+
if (matches == 0)
{
result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", arg);
@@ -892,7 +926,7 @@ protected:
ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(global_idx));
if (!valobj_sp)
valobj_sp = ValueObjectVariable::Create (m_exe_ctx.GetBestExecutionContextScope(), var_sp);
-
+
if (valobj_sp)
DumpValueObject (s, var_sp, valobj_sp, use_var_name ? var_sp->GetName().GetCString() : arg);
}
@@ -939,7 +973,7 @@ protected:
comp_unit->GetPath().c_str());
else
result.AppendErrorWithFormat ("no debug information for frame %u\n", frame->GetFrameIndex());
- }
+ }
else
result.AppendError ("'target variable' takes one or more global variable names as arguments\n");
result.SetStatus (eReturnStatusFailed);
@@ -956,7 +990,7 @@ protected:
{
const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx));
ModuleSpec module_spec (module_file);
-
+
ModuleSP module_sp (target->GetImages().FindFirstModule(module_spec));
if (module_sp)
{
@@ -986,7 +1020,7 @@ protected:
for (size_t cu_idx=0; cu_idx<num_compile_units; ++cu_idx)
target->GetImages().FindCompileUnits(compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
}
-
+
const uint32_t num_scs = sc_list.GetSize();
if (num_scs > 0)
{
@@ -1022,10 +1056,10 @@ protected:
m_cmd_name.c_str());
m_interpreter.TruncationWarningGiven();
}
-
+
return result.Succeeded();
}
-
+
OptionGroupOptions m_option_group;
OptionGroupVariable m_option_variable;
OptionGroupFormat m_option_format;
@@ -1051,15 +1085,15 @@ public:
CommandArgumentEntry arg;
CommandArgumentData old_prefix_arg;
CommandArgumentData new_prefix_arg;
-
+
// Define the first variant of this arg pair.
old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
-
+
// Define the first variant of this arg pair.
new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
-
+
// There are two required arguments that must always occur together, i.e. an argument "pair". Because they
// must always occur together, they are treated as two variants of one argument rather than two independent
// arguments. Push them both into the first argument position for m_arguments...
@@ -1094,7 +1128,7 @@ protected:
{
const char *from = command.GetArgumentAtIndex(i);
const char *to = command.GetArgumentAtIndex(i+1);
-
+
if (from[0] && to[0])
{
bool last_pair = ((argc - i) == 2);
@@ -1179,7 +1213,7 @@ public:
CommandArgumentData index_arg;
CommandArgumentData old_prefix_arg;
CommandArgumentData new_prefix_arg;
-
+
// Define the first and only variant of this arg.
index_arg.arg_type = eArgTypeIndex;
index_arg.arg_repetition = eArgRepeatPlain;
@@ -1190,11 +1224,11 @@ public:
// Define the first variant of this arg pair.
old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
-
+
// Define the first variant of this arg pair.
new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
-
+
// There are two required arguments that must always occur together, i.e. an argument "pair". Because they
// must always occur together, they are treated as two variants of one argument rather than two independent
// arguments. Push them both into the same argument position for m_arguments...
@@ -1242,7 +1276,7 @@ protected:
{
const char *from = command.GetArgumentAtIndex(i);
const char *to = command.GetArgumentAtIndex(i+1);
-
+
if (from[0] && to[0])
{
bool last_pair = ((argc - i) == 2);
@@ -1341,14 +1375,14 @@ public:
{
CommandArgumentEntry arg;
CommandArgumentData path_arg;
-
+
// Define the first (and only) variant of this arg.
path_arg.arg_type = eArgTypeDirectoryName;
path_arg.arg_repetition = eArgRepeatPlain;
-
+
// There is only one variant this argument could be; put it into the argument entry.
arg.push_back (path_arg);
-
+
// Push the data for the first argument into the m_arguments vector.
m_arguments.push_back (arg);
}
@@ -1435,7 +1469,7 @@ DumpCompileUnitLineTable (CommandInterpreter &interpreter,
false,
eSymbolContextCompUnit,
sc_list);
-
+
for (uint32_t i=0; i<num_matches; ++i)
{
SymbolContext sc;
@@ -1443,7 +1477,7 @@ DumpCompileUnitLineTable (CommandInterpreter &interpreter,
{
if (i > 0)
strm << "\n\n";
-
+
strm << "Line table for " << *static_cast<FileSpec*> (sc.comp_unit) << " in `"
<< module->GetFileSpec().GetFilename() << "\n";
LineTable *line_table = sc.comp_unit->GetLineTable();
@@ -1612,7 +1646,7 @@ LookupAddressInModule (CommandInterpreter &interpreter,
if (!module->ResolveFileAddress (addr, so_addr))
return false;
}
-
+
ExecutionContextScope *exe_scope = interpreter.GetExecutionContext().GetBestExecutionContextScope();
DumpAddress (exe_scope, so_addr, verbose, strm);
// strm.IndentMore();
@@ -1635,7 +1669,7 @@ LookupAddressInModule (CommandInterpreter &interpreter,
// strm.IndentLess();
return true;
}
-
+
return false;
}
@@ -1645,7 +1679,7 @@ LookupSymbolInModule (CommandInterpreter &interpreter, Stream &strm, Module *mod
if (module)
{
SymbolContext sc;
-
+
SymbolVendor *sym_vendor = module->GetSymbolVendor ();
if (sym_vendor)
{
@@ -1667,8 +1701,7 @@ LookupSymbolInModule (CommandInterpreter &interpreter, Stream &strm, Module *mod
{
num_matches = symtab->AppendSymbolIndexesWithName (symbol_name, match_indexes);
}
-
-
+
if (num_matches > 0)
{
strm.Indent ();
@@ -1705,19 +1738,19 @@ DumpSymbolContextList (ExecutionContextScope *exe_scope, Stream &strm, SymbolCon
strm.IndentMore ();
uint32_t i;
const uint32_t num_matches = sc_list.GetSize();
-
+
for (i=0; i<num_matches; ++i)
{
SymbolContext sc;
if (sc_list.GetContextAtIndex(i, sc))
{
AddressRange range;
-
+
sc.GetAddressRange(eSymbolContextEverything,
0,
true,
range);
-
+
DumpAddress (exe_scope, range.GetBaseAddress(), verbose, strm);
}
}
@@ -1759,11 +1792,11 @@ LookupFunctionInModule (CommandInterpreter &interpreter,
append,
sc_list);
}
-
+
if (num_matches)
{
strm.Indent ();
- strm.Printf("%zu match%s found in ", num_matches, num_matches > 1 ? "es" : "");
+ strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, num_matches > 1 ? "es" : "");
DumpFullpath (strm, &module->GetFileSpec(), 0);
strm.PutCString(":\n");
DumpSymbolContextList (interpreter.GetExecutionContext().GetBestExecutionContextScope(), strm, sc_list, verbose);
@@ -1790,11 +1823,11 @@ LookupTypeInModule (CommandInterpreter &interpreter,
ConstString name(name_cstr);
num_matches = module->FindTypes(sc, name, name_is_fully_qualified, max_num_matches, type_list);
-
+
if (num_matches)
{
strm.Indent ();
- strm.Printf("%zu match%s found in ", num_matches, num_matches > 1 ? "es" : "");
+ strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, num_matches > 1 ? "es" : "");
DumpFullpath (strm, &module->GetFileSpec(), 0);
strm.PutCString(":\n");
for (TypeSP type_sp : type_list.Types())
@@ -1835,22 +1868,22 @@ LookupTypeHere (CommandInterpreter &interpreter,
{
if (!sym_ctx.module_sp)
return 0;
-
+
TypeList type_list;
const uint32_t max_num_matches = UINT32_MAX;
size_t num_matches = 1;
bool name_is_fully_qualified = false;
-
+
ConstString name(name_cstr);
num_matches = sym_ctx.module_sp->FindTypes(sym_ctx, name, name_is_fully_qualified, max_num_matches, type_list);
-
+
if (num_matches)
{
strm.Indent ();
strm.PutCString("Best match found in ");
DumpFullpath (strm, &sym_ctx.module_sp->GetFileSpec(), 0);
strm.PutCString(":\n");
-
+
TypeSP type_sp (type_list.GetTypeAtIndex(0));
if (type_sp)
{
@@ -1905,7 +1938,6 @@ LookupFileAndLineInModule (CommandInterpreter &interpreter,
}
}
return 0;
-
}
@@ -1918,7 +1950,7 @@ FindModulesByName (Target *target,
// Dump specified images (by basename or fullpath)
FileSpec module_file_spec(module_name, false);
ModuleSpec module_spec (module_file_spec);
-
+
const size_t initial_size = module_list.GetSize ();
if (check_global_list)
@@ -1930,7 +1962,7 @@ FindModulesByName (Target *target,
for (size_t image_idx = 0; image_idx<num_modules; ++image_idx)
{
Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
-
+
if (module)
{
if (module->MatchesModuleSpec (module_spec))
@@ -1946,7 +1978,7 @@ FindModulesByName (Target *target,
if (target)
{
const size_t num_matches = target->GetImages().FindModules (module_spec, module_list);
-
+
// Not found in our module list for our target, check the main
// shared module list in case it is a extra file used somewhere
// else
@@ -1961,7 +1993,7 @@ FindModulesByName (Target *target,
ModuleList::FindSharedModules (module_spec,module_list);
}
}
-
+
return module_list.GetSize () - initial_size;
}
@@ -1975,7 +2007,6 @@ FindModulesByName (Target *target,
class CommandObjectTargetModulesModuleAutoComplete : public CommandObjectParsed
{
public:
-
CommandObjectTargetModulesModuleAutoComplete (CommandInterpreter &interpreter,
const char *name,
const char *help,
@@ -1984,23 +2015,23 @@ public:
{
CommandArgumentEntry arg;
CommandArgumentData file_arg;
-
+
// Define the first (and only) variant of this arg.
file_arg.arg_type = eArgTypeFilename;
file_arg.arg_repetition = eArgRepeatStar;
-
+
// There is only one variant this argument could be; put it into the argument entry.
arg.push_back (file_arg);
-
+
// Push the data for the first argument into the m_arguments vector.
m_arguments.push_back (arg);
}
-
+
virtual
~CommandObjectTargetModulesModuleAutoComplete ()
{
}
-
+
virtual int
HandleArgumentCompletion (Args &input,
int &cursor_index,
@@ -2014,7 +2045,7 @@ public:
// Arguments are the standard module completer.
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
-
+
CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
CommandCompletions::eModuleCompletion,
completion_str.c_str(),
@@ -2037,7 +2068,6 @@ public:
class CommandObjectTargetModulesSourceFileAutoComplete : public CommandObjectParsed
{
public:
-
CommandObjectTargetModulesSourceFileAutoComplete (CommandInterpreter &interpreter,
const char *name,
const char *help,
@@ -2047,23 +2077,23 @@ public:
{
CommandArgumentEntry arg;
CommandArgumentData source_file_arg;
-
+
// Define the first (and only) variant of this arg.
source_file_arg.arg_type = eArgTypeSourceFile;
source_file_arg.arg_repetition = eArgRepeatPlus;
-
+
// There is only one variant this argument could be; put it into the argument entry.
arg.push_back (source_file_arg);
-
+
// Push the data for the first argument into the m_arguments vector.
m_arguments.push_back (arg);
}
-
+
virtual
~CommandObjectTargetModulesSourceFileAutoComplete ()
{
}
-
+
virtual int
HandleArgumentCompletion (Args &input,
int &cursor_index,
@@ -2077,7 +2107,7 @@ public:
// Arguments are the standard source file completer.
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
-
+
CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
CommandCompletions::eSourceFileCompletion,
completion_str.c_str(),
@@ -2105,39 +2135,38 @@ public:
m_options (interpreter)
{
}
-
+
virtual
~CommandObjectTargetModulesDumpSymtab ()
{
}
-
+
virtual Options *
GetOptions ()
{
return &m_options;
}
-
+
class CommandOptions : public Options
{
public:
-
CommandOptions (CommandInterpreter &interpreter) :
Options(interpreter),
m_sort_order (eSortOrderNone)
{
}
-
+
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 's':
@@ -2146,33 +2175,33 @@ public:
eSortOrderNone,
error);
break;
-
+
default:
error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
break;
-
+
}
return error;
}
-
+
void
OptionParsingStarting ()
{
m_sort_order = eSortOrderNone;
}
-
+
const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
-
+
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table[];
-
+
SortOrder m_sort_order;
};
-
+
protected:
virtual bool
DoExecute (Args& command,
@@ -2188,11 +2217,11 @@ protected:
else
{
uint32_t num_dumped = 0;
-
+
uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
result.GetOutputStream().SetAddressByteSize(addr_byte_size);
result.GetErrorStream().SetAddressByteSize(addr_byte_size);
-
+
if (command.GetArgumentCount() == 0)
{
// Dump all sections for all modules images
@@ -2200,7 +2229,7 @@ protected:
const size_t num_modules = target->GetImages().GetSize();
if (num_modules > 0)
{
- result.GetOutputStream().Printf("Dumping symbol table for %zu modules.\n", num_modules);
+ result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64 " modules.\n", (uint64_t)num_modules);
for (size_t image_idx = 0; image_idx<num_modules; ++image_idx)
{
if (num_dumped > 0)
@@ -2251,7 +2280,7 @@ protected:
result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
}
}
-
+
if (num_dumped > 0)
result.SetStatus (eReturnStatusSuccessFinishResult);
else
@@ -2262,8 +2291,7 @@ protected:
}
return result.Succeeded();
}
-
-
+
CommandOptions m_options;
};
@@ -2280,8 +2308,8 @@ g_sort_option_enumeration[4] =
OptionDefinition
CommandObjectTargetModulesDumpSymtab::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "sort", 's', OptionParser::eRequiredArgument, g_sort_option_enumeration, 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_1, false, "sort", 's', OptionParser::eRequiredArgument, NULL, g_sort_option_enumeration, 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#pragma mark CommandObjectTargetModulesDumpSections
@@ -2301,12 +2329,12 @@ public:
NULL)
{
}
-
+
virtual
~CommandObjectTargetModulesDumpSections ()
{
}
-
+
protected:
virtual bool
DoExecute (Args& command,
@@ -2322,18 +2350,18 @@ protected:
else
{
uint32_t num_dumped = 0;
-
+
uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
result.GetOutputStream().SetAddressByteSize(addr_byte_size);
result.GetErrorStream().SetAddressByteSize(addr_byte_size);
-
+
if (command.GetArgumentCount() == 0)
{
// Dump all sections for all modules images
const size_t num_modules = target->GetImages().GetSize();
if (num_modules > 0)
{
- result.GetOutputStream().Printf("Dumping sections for %zu modules.\n", num_modules);
+ result.GetOutputStream().Printf("Dumping sections for %" PRIu64 " modules.\n", (uint64_t)num_modules);
for (size_t image_idx = 0; image_idx<num_modules; ++image_idx)
{
num_dumped++;
@@ -2376,7 +2404,7 @@ protected:
}
}
}
-
+
if (num_dumped > 0)
result.SetStatus (eReturnStatusSuccessFinishResult);
else
@@ -2407,12 +2435,12 @@ public:
NULL)
{
}
-
+
virtual
~CommandObjectTargetModulesDumpSymfile ()
{
}
-
+
protected:
virtual bool
DoExecute (Args& command,
@@ -2428,11 +2456,11 @@ protected:
else
{
uint32_t num_dumped = 0;
-
+
uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
result.GetOutputStream().SetAddressByteSize(addr_byte_size);
result.GetErrorStream().SetAddressByteSize(addr_byte_size);
-
+
if (command.GetArgumentCount() == 0)
{
// Dump all sections for all modules images
@@ -2441,7 +2469,7 @@ protected:
const size_t num_modules = target_modules.GetSize();
if (num_modules > 0)
{
- result.GetOutputStream().Printf("Dumping debug symbols for %zu modules.\n", num_modules);
+ result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64 " modules.\n", (uint64_t)num_modules);
for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
{
if (DumpModuleSymbolVendor (result.GetOutputStream(), target_modules.GetModulePointerAtIndexUnlocked(image_idx)))
@@ -2479,7 +2507,7 @@ protected:
result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
}
}
-
+
if (num_dumped > 0)
result.SetStatus (eReturnStatusSuccessFinishResult);
else
@@ -2510,12 +2538,12 @@ public:
eFlagRequiresTarget)
{
}
-
+
virtual
~CommandObjectTargetModulesDumpLineTable ()
{
}
-
+
protected:
virtual bool
DoExecute (Args& command,
@@ -2523,11 +2551,11 @@ protected:
{
Target *target = m_exe_ctx.GetTargetPtr();
uint32_t total_num_dumped = 0;
-
+
uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
result.GetOutputStream().SetAddressByteSize(addr_byte_size);
result.GetErrorStream().SetAddressByteSize(addr_byte_size);
-
+
if (command.GetArgumentCount() == 0)
{
result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str());
@@ -2540,7 +2568,7 @@ protected:
for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
{
FileSpec file_spec(arg_cstr, false);
-
+
const ModuleList &target_modules = target->GetImages();
Mutex::Locker modules_locker(target_modules.GetMutex());
const size_t num_modules = target_modules.GetSize();
@@ -2563,7 +2591,7 @@ protected:
}
}
}
-
+
if (total_num_dumped > 0)
result.SetStatus (eReturnStatusSuccessFinishResult);
else
@@ -2585,7 +2613,6 @@ protected:
class CommandObjectTargetModulesDump : public CommandObjectMultiword
{
public:
-
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
@@ -2600,7 +2627,7 @@ public:
LoadSubCommand ("symfile", CommandObjectSP (new CommandObjectTargetModulesDumpSymfile (interpreter)));
LoadSubCommand ("line-table", CommandObjectSP (new CommandObjectTargetModulesDumpLineTable (interpreter)));
}
-
+
virtual
~CommandObjectTargetModulesDump()
{
@@ -2622,18 +2649,18 @@ public:
m_option_group.Append (&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Finalize();
}
-
+
virtual
~CommandObjectTargetModulesAdd ()
{
}
-
+
virtual Options *
GetOptions ()
{
return &m_option_group;
}
-
+
virtual int
HandleArgumentCompletion (Args &input,
int &cursor_index,
@@ -2646,7 +2673,7 @@ public:
{
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
-
+
CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
CommandCompletions::eDiskFileCompletion,
completion_str.c_str(),
@@ -2659,11 +2686,9 @@ public:
}
protected:
-
OptionGroupOptions m_option_group;
OptionGroupUUID m_uuid_option_group;
OptionGroupFile m_symbol_file;
-
virtual bool
DoExecute (Args& args,
@@ -2679,7 +2704,7 @@ protected:
else
{
bool flush = false;
-
+
const size_t argc = args.GetArgumentCount();
if (argc == 0)
{
@@ -2700,8 +2725,6 @@ protected:
}
else
{
- flush = true;
-
StreamString strm;
module_spec.GetUUID().Dump (&strm);
if (module_spec.GetFileSpec())
@@ -2798,7 +2821,7 @@ protected:
}
}
}
-
+
if (flush)
{
ProcessSP process = target->GetProcessSP();
@@ -2806,7 +2829,7 @@ protected:
process->Flush();
}
}
-
+
return result.Succeeded();
}
@@ -2829,18 +2852,18 @@ public:
m_option_group.Append (&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Finalize();
}
-
+
virtual
~CommandObjectTargetModulesLoad ()
{
}
-
+
virtual Options *
GetOptions ()
{
return &m_option_group;
}
-
+
protected:
virtual bool
DoExecute (Args& args,
@@ -2863,7 +2886,7 @@ protected:
search_using_module_spec = true;
module_spec.GetFileSpec() = m_file_option.GetOptionValue().GetCurrentValue();
}
-
+
if (m_uuid_option_group.GetOptionValue().OptionWasSet())
{
search_using_module_spec = true;
@@ -2872,7 +2895,6 @@ protected:
if (search_using_module_spec)
{
-
ModuleList matching_modules;
const size_t num_matches = target->GetImages().FindModules (module_spec, matching_modules);
@@ -2965,7 +2987,7 @@ protected:
}
}
}
-
+
if (changed)
{
target->ModulesDidLoad (matching_modules);
@@ -3004,7 +3026,7 @@ protected:
else
{
std::string uuid_str;
-
+
if (module_spec.GetFileSpec())
module_spec.GetFileSpec().GetPath (path, sizeof(path));
else
@@ -3044,8 +3066,8 @@ protected:
}
}
return result.Succeeded();
- }
-
+ }
+
OptionGroupOptions m_option_group;
OptionGroupUUID m_uuid_option_group;
OptionGroupFile m_file_option;
@@ -3058,11 +3080,9 @@ protected:
class CommandObjectTargetModulesList : public CommandObjectParsed
{
public:
-
class CommandOptions : public Options
{
public:
-
CommandOptions (CommandInterpreter &interpreter) :
Options(interpreter),
m_format_array(),
@@ -3070,12 +3090,12 @@ public:
m_module_addr (LLDB_INVALID_ADDRESS)
{
}
-
+
virtual
~CommandOptions ()
{
}
-
+
virtual Error
SetOptionValue (uint32_t option_idx, const char *option_arg)
{
@@ -3100,7 +3120,7 @@ public:
}
return error;
}
-
+
void
OptionParsingStarting ()
{
@@ -3108,24 +3128,24 @@ public:
m_use_global_module_list = false;
m_module_addr = LLDB_INVALID_ADDRESS;
}
-
+
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.
typedef std::vector< std::pair<char, uint32_t> > FormatWidthCollection;
FormatWidthCollection m_format_array;
bool m_use_global_module_list;
lldb::addr_t m_module_addr;
};
-
+
CommandObjectTargetModulesList (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"target modules list",
@@ -3134,19 +3154,19 @@ public:
m_options (interpreter)
{
}
-
+
virtual
~CommandObjectTargetModulesList ()
{
}
-
+
virtual
Options *
GetOptions ()
{
return &m_options;
}
-
+
protected:
virtual bool
DoExecute (Args& command,
@@ -3174,7 +3194,7 @@ protected:
}
// Dump all sections for all modules images
Stream &strm = result.GetOutputStream();
-
+
if (m_options.m_module_addr != LLDB_INVALID_ADDRESS)
{
if (target)
@@ -3207,7 +3227,7 @@ protected:
}
return result.Succeeded();
}
-
+
size_t num_modules = 0;
Mutex::Locker locker; // This locker will be locked on the mutex in module_list_ptr if it is non-NULL.
// Otherwise it will lock the AllocationModuleCollectionMutex when accessing
@@ -3243,10 +3263,10 @@ protected:
}
}
}
-
+
module_list_ptr = &module_list;
}
-
+
if (module_list_ptr != NULL)
{
locker.Lock(module_list_ptr->GetMutex());
@@ -3254,7 +3274,7 @@ protected:
}
if (num_modules > 0)
- {
+ {
for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
{
ModuleSP module_sp;
@@ -3269,7 +3289,7 @@ protected:
module = Module::GetAllocatedModuleAtIndex(image_idx);
module_sp = module->shared_from_this();
}
-
+
const size_t indent = strm.Printf("[%3u] ", image_idx);
PrintModule (target, module, indent, strm);
@@ -3308,7 +3328,7 @@ protected:
strm.PutCString("Null module");
return;
}
-
+
bool dump_object_name = false;
if (m_options.m_format_array.empty())
{
@@ -3331,25 +3351,25 @@ protected:
case 'A':
DumpModuleArchitecture (strm, module, false, width);
break;
-
+
case 't':
DumpModuleArchitecture (strm, module, true, width);
break;
-
+
case 'f':
DumpFullpath (strm, &module->GetFileSpec(), width);
dump_object_name = true;
break;
-
+
case 'd':
DumpDirectory (strm, &module->GetFileSpec(), width);
break;
-
+
case 'b':
DumpBasename (strm, &module->GetFileSpec(), width);
dump_object_name = true;
break;
-
+
case 'h':
case 'o':
// Image header address
@@ -3402,9 +3422,9 @@ protected:
ref_count = module_sp.use_count() - 1;
}
if (width)
- strm.Printf("{%*zu}", width, ref_count);
+ strm.Printf("{%*" PRIu64 "}", width, (uint64_t)ref_count);
else
- strm.Printf("{%zu}", ref_count);
+ strm.Printf("{%" PRIu64 "}", (uint64_t)ref_count);
}
break;
@@ -3437,23 +3457,23 @@ protected:
strm.Printf("%.*s", width, "<NONE>");
}
break;
-
+
case 'm':
module->GetModificationTime().Dump(&strm, width);
break;
case 'p':
- strm.Printf("%p", module);
+ strm.Printf("%p", static_cast<void*>(module));
break;
case 'u':
DumpModuleUUID(strm, module);
break;
-
+
default:
break;
}
-
+
}
if (dump_object_name)
{
@@ -3463,29 +3483,29 @@ protected:
}
strm.EOL();
}
-
+
CommandOptions m_options;
};
OptionDefinition
CommandObjectTargetModulesList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression, "Display the image at this address."},
- { LLDB_OPT_SET_1, false, "arch", 'A', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the architecture when listing images."},
- { LLDB_OPT_SET_1, false, "triple", 't', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the triple when listing images."},
- { LLDB_OPT_SET_1, false, "header", 'h', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Display the image header address as a load address if debugging, a file address otherwise."},
- { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Display the image header address offset from the header file address (the slide amount)."},
- { LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Display the UUID when listing images."},
- { LLDB_OPT_SET_1, false, "fullpath", 'f', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the fullpath to the image object file."},
- { LLDB_OPT_SET_1, false, "directory", 'd', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the directory with optional width for the image object file."},
- { LLDB_OPT_SET_1, false, "basename", 'b', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the basename with optional width for the image object file."},
- { LLDB_OPT_SET_1, false, "symfile", 's', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width."},
- { LLDB_OPT_SET_1, false, "symfile-unique", 'S', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the symbol file with optional width only if it is different from the executable object file."},
- { LLDB_OPT_SET_1, false, "mod-time", 'm', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the modification time with optional width of the module."},
- { LLDB_OPT_SET_1, false, "ref-count", 'r', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the reference count if the module is still in the shared module cache."},
- { LLDB_OPT_SET_1, false, "pointer", 'p', OptionParser::eOptionalArgument, NULL, 0, eArgTypeNone, "Display the module pointer."},
- { LLDB_OPT_SET_1, false, "global", 'g', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, "Display the image at this address."},
+ { LLDB_OPT_SET_1, false, "arch", 'A', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeWidth, "Display the architecture when listing images."},
+ { LLDB_OPT_SET_1, false, "triple", 't', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeWidth, "Display the triple when listing images."},
+ { LLDB_OPT_SET_1, false, "header", 'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the image header address as a load address if debugging, a file address otherwise."},
+ { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the image header address offset from the header file address (the slide amount)."},
+ { LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the UUID when listing images."},
+ { LLDB_OPT_SET_1, false, "fullpath", 'f', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeWidth, "Display the fullpath to the image object file."},
+ { LLDB_OPT_SET_1, false, "directory", 'd', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeWidth, "Display the directory with optional width for the image object file."},
+ { LLDB_OPT_SET_1, false, "basename", 'b', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeWidth, "Display the basename with optional width for the image object file."},
+ { LLDB_OPT_SET_1, false, "symfile", 's', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width."},
+ { LLDB_OPT_SET_1, false, "symfile-unique", 'S', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeWidth, "Display the symbol file with optional width only if it is different from the executable object file."},
+ { LLDB_OPT_SET_1, false, "mod-time", 'm', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeWidth, "Display the modification time with optional width of the module."},
+ { LLDB_OPT_SET_1, false, "ref-count", 'r', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeWidth, "Display the reference count if the module is still in the shared module cache."},
+ { LLDB_OPT_SET_1, false, "pointer", 'p', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeNone, "Display the module pointer."},
+ { LLDB_OPT_SET_1, false, "global", 'g', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#pragma mark CommandObjectTargetModulesShowUnwind
@@ -3584,7 +3604,7 @@ public:
std::string m_str; // Holds name lookup
lldb::addr_t m_addr; // Holds the address to lookup
};
-
+
CommandObjectTargetModulesShowUnwind (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"target modules show-unwind",
@@ -3597,12 +3617,12 @@ public:
m_options (interpreter)
{
}
-
+
virtual
~CommandObjectTargetModulesShowUnwind ()
{
}
-
+
virtual
Options *
GetOptions ()
@@ -3645,7 +3665,7 @@ protected:
}
SymbolContextList sc_list;
-
+
if (m_options.m_type == eLookupTypeFunctionOrSymbol)
{
ConstString function_name (m_options.m_str.c_str());
@@ -3711,7 +3731,7 @@ protected:
result.GetOutputStream().Printf ("\n");
}
- UnwindPlanSP non_callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtNonCallSite(*thread.get());
+ 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);
@@ -3755,9 +3775,9 @@ protected:
OptionDefinition
CommandObjectTargetModulesShowUnwind::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "name", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name."},
- { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address"},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_1, false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name."},
+ { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address"},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//----------------------------------------------------------------------
@@ -3766,7 +3786,6 @@ CommandObjectTargetModulesShowUnwind::CommandOptions::g_option_table[] =
class CommandObjectTargetModulesLookup : public CommandObjectParsed
{
public:
-
enum
{
eLookupTypeInvalid = -1,
@@ -3778,29 +3797,28 @@ public:
eLookupTypeType,
kNumLookupTypes
};
-
+
class CommandOptions : public Options
{
public:
-
CommandOptions (CommandInterpreter &interpreter) :
Options(interpreter)
{
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 'a':
@@ -3810,27 +3828,27 @@ public:
m_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
}
break;
-
+
case 'o':
m_offset = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
if (m_offset == LLDB_INVALID_ADDRESS)
error.SetErrorStringWithFormat ("invalid offset string '%s'", option_arg);
break;
-
+
case 's':
m_str = option_arg;
m_type = eLookupTypeSymbol;
break;
-
+
case 'f':
m_file.SetFile (option_arg, false);
m_type = eLookupTypeFileLine;
break;
-
+
case 'i':
m_include_inlines = false;
break;
-
+
case 'l':
m_line_number = Args::StringToUInt32(option_arg, UINT32_MAX);
if (m_line_number == UINT32_MAX)
@@ -3839,12 +3857,12 @@ public:
error.SetErrorString ("zero is an invalid line number");
m_type = eLookupTypeFileLine;
break;
-
+
case 'F':
m_str = option_arg;
m_type = eLookupTypeFunction;
break;
-
+
case 'n':
m_str = option_arg;
m_type = eLookupTypeFunctionOrSymbol;
@@ -3854,23 +3872,23 @@ public:
m_str = option_arg;
m_type = eLookupTypeType;
break;
-
+
case 'v':
m_verbose = 1;
break;
-
+
case 'A':
m_print_all = true;
break;
-
+
case 'r':
m_use_regex = true;
break;
}
-
+
return error;
}
-
+
void
OptionParsingStarting ()
{
@@ -3885,15 +3903,15 @@ public:
m_verbose = false;
m_print_all = false;
}
-
+
const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
-
+
// Options table: Required for subclasses of Options.
-
+
static OptionDefinition g_option_table[];
int m_type; // Should be a eLookupTypeXXX enum after parsing options
std::string m_str; // Holds name lookup
@@ -3905,9 +3923,8 @@ public:
bool m_include_inlines;// Check for inline entries when looking up by file/line.
bool m_verbose; // Enable verbose lookup info
bool m_print_all; // Print all matches, even in cases where there's a best match.
-
};
-
+
CommandObjectTargetModulesLookup (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"target modules lookup",
@@ -3918,29 +3935,29 @@ public:
{
CommandArgumentEntry arg;
CommandArgumentData file_arg;
-
+
// Define the first (and only) variant of this arg.
file_arg.arg_type = eArgTypeFilename;
file_arg.arg_repetition = eArgRepeatStar;
-
+
// There is only one variant this argument could be; put it into the argument entry.
arg.push_back (file_arg);
-
+
// Push the data for the first argument into the m_arguments vector.
m_arguments.push_back (arg);
}
-
+
virtual
~CommandObjectTargetModulesLookup ()
{
}
-
+
virtual Options *
GetOptions ()
{
return &m_options;
}
-
+
bool
LookupHere (CommandInterpreter &interpreter, CommandReturnObject &result, bool &syntax_error)
{
@@ -3956,17 +3973,17 @@ public:
case eLookupTypeType:
break;
}
-
+
StackFrameSP frame = m_exe_ctx.GetFrameSP();
-
+
if (!frame)
return false;
-
+
const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule));
-
+
if (!sym_ctx.module_sp)
return false;
-
+
switch (m_options.m_type)
{
default:
@@ -3986,10 +4003,10 @@ public:
}
break;
}
-
+
return true;
}
-
+
bool
LookupInModule (CommandInterpreter &interpreter, Module *module, CommandReturnObject &result, bool &syntax_error)
{
@@ -4011,7 +4028,7 @@ public:
}
}
break;
-
+
case eLookupTypeSymbol:
if (!m_options.m_str.empty())
{
@@ -4027,11 +4044,10 @@ public:
}
}
break;
-
+
case eLookupTypeFileLine:
if (m_options.m_file)
{
-
if (LookupFileAndLineInModule (m_interpreter,
result.GetOutputStream(),
module,
@@ -4064,8 +4080,7 @@ public:
}
}
break;
-
-
+
case eLookupTypeType:
if (!m_options.m_str.empty())
{
@@ -4080,17 +4095,17 @@ public:
}
}
break;
-
+
default:
m_options.GenerateOptionUsage (result.GetErrorStream(), this);
syntax_error = true;
break;
}
-
+
result.SetStatus (eReturnStatusFailed);
return false;
}
-
+
protected:
virtual bool
DoExecute (Args& command,
@@ -4112,11 +4127,11 @@ protected:
result.GetOutputStream().SetAddressByteSize(addr_byte_size);
result.GetErrorStream().SetAddressByteSize(addr_byte_size);
// Dump all sections for all modules images
-
+
if (command.GetArgumentCount() == 0)
{
ModuleSP current_module;
-
+
// Where it is possible to look in the current symbol context
// first, try that. If this search was successful and --all
// was not passed, don't print anything else.
@@ -4130,9 +4145,9 @@ protected:
return result.Succeeded();
}
}
-
+
// Dump all sections for all other modules
-
+
const ModuleList &target_modules = target->GetImages();
Mutex::Locker modules_locker(target_modules.GetMutex());
const size_t num_modules = target_modules.GetSize();
@@ -4141,7 +4156,7 @@ protected:
for (i = 0; i<num_modules && syntax_error == false; ++i)
{
Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked(i);
-
+
if (module_pointer != current_module.get() &&
LookupInModule (m_interpreter, target_modules.GetModulePointerAtIndexUnlocked(i), result, syntax_error))
{
@@ -4184,7 +4199,7 @@ protected:
result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
}
}
-
+
if (num_successful_lookups > 0)
result.SetStatus (eReturnStatusSuccessFinishResult);
else
@@ -4192,29 +4207,29 @@ protected:
}
return result.Succeeded();
}
-
+
CommandOptions m_options;
};
OptionDefinition
CommandObjectTargetModulesLookup::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, true, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules."},
- { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "When looking up an address subtract <offset> from any addresses before doing the lookup."},
+ { LLDB_OPT_SET_1, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules."},
+ { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "When looking up an address subtract <offset> from any addresses before doing the lookup."},
{ LLDB_OPT_SET_2| LLDB_OPT_SET_4 | LLDB_OPT_SET_5
/* FIXME: re-enable this for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */ ,
- false, "regex", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions."},
- { LLDB_OPT_SET_2, true, "symbol", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeSymbol, "Lookup a symbol by name in the symbol tables in one or more target modules."},
- { LLDB_OPT_SET_3, true, "file", 'f', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules."},
- { LLDB_OPT_SET_3, false, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)."},
+ false, "regex", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions."},
+ { LLDB_OPT_SET_2, true, "symbol", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeSymbol, "Lookup a symbol by name in the symbol tables in one or more target modules."},
+ { LLDB_OPT_SET_3, true, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules."},
+ { LLDB_OPT_SET_3, false, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)."},
{ LLDB_OPT_SET_FROM_TO(3,5),
- false, "no-inlines", 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Ignore inline entries (must be used in conjunction with --file or --function)."},
- { LLDB_OPT_SET_4, true, "function", 'F', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more target modules."},
- { LLDB_OPT_SET_5, true, "name", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFunctionOrSymbol, "Lookup a function or symbol by name in one or more target modules."},
- { LLDB_OPT_SET_6, true, "type", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Lookup a type by name in the debug symbols in one or more target modules."},
- { LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Enable verbose lookup information."},
- { LLDB_OPT_SET_ALL, false, "all", 'A', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ false, "no-inlines", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Ignore inline entries (must be used in conjunction with --file or --function)."},
+ { LLDB_OPT_SET_4, true, "function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more target modules."},
+ { LLDB_OPT_SET_5, true, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFunctionOrSymbol, "Lookup a function or symbol by name in one or more target modules."},
+ { LLDB_OPT_SET_6, true, "type", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Lookup a type by name in the debug symbols in one or more target modules."},
+ { LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Enable verbose lookup information."},
+ { LLDB_OPT_SET_ALL, false, "all", 'A', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -4227,7 +4242,6 @@ CommandObjectTargetModulesLookup::CommandOptions::g_option_table[] =
class CommandObjectTargetModulesImageSearchPaths : public CommandObjectMultiword
{
public:
-
CommandObjectTargetModulesImageSearchPaths (CommandInterpreter &interpreter) :
CommandObjectMultiword (interpreter,
"target modules search-paths",
@@ -4240,7 +4254,7 @@ public:
LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetModulesSearchPathsList (interpreter)));
LoadSubCommand ("query", CommandObjectSP (new CommandObjectTargetModulesSearchPathsQuery (interpreter)));
}
-
+
~CommandObjectTargetModulesImageSearchPaths()
{
}
@@ -4279,7 +4293,7 @@ public:
~CommandObjectTargetModules()
{
}
-
+
private:
//------------------------------------------------------------------
// For CommandObjectTargetModules only
@@ -4307,12 +4321,12 @@ public:
m_option_group.Append (&m_current_frame_option, LLDB_OPT_SET_2, LLDB_OPT_SET_2);
m_option_group.Finalize();
}
-
+
virtual
~CommandObjectTargetSymbolsAdd ()
{
}
-
+
virtual int
HandleArgumentCompletion (Args &input,
int &cursor_index,
@@ -4325,7 +4339,7 @@ public:
{
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
-
+
CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
CommandCompletions::eDiskFileCompletion,
completion_str.c_str(),
@@ -4336,16 +4350,14 @@ public:
matches);
return matches.GetSize();
}
-
+
virtual Options *
GetOptions ()
{
return &m_option_group;
}
-
protected:
-
bool
AddModuleSymbols (Target *target,
ModuleSpec &module_spec,
@@ -4357,7 +4369,7 @@ protected:
{
char symfile_path[PATH_MAX];
symbol_fspec.GetPath (symfile_path, sizeof(symfile_path));
-
+
if (!module_spec.GetUUID().IsValid())
{
if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
@@ -4368,7 +4380,7 @@ protected:
// current target, so we need to find that module in the
// target
ModuleList matching_module_list;
-
+
size_t num_matches = 0;
// First extract all module specs from the symbol file
lldb_private::ModuleSpecList symfile_module_specs;
@@ -4389,7 +4401,7 @@ protected:
num_matches = target->GetImages().FindModules (symfile_uuid_module_spec, matching_module_list);
}
}
-
+
if (num_matches == 0)
{
// No matches yet, iterate through the module specs to find a UUID value that
@@ -4405,7 +4417,7 @@ protected:
ModuleSpec symfile_uuid_module_spec;
symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
num_matches = target->GetImages().FindModules (symfile_uuid_module_spec, matching_module_list);
- }
+ }
}
}
}
@@ -4414,23 +4426,22 @@ protected:
// Just try to match up the file by basename if we have no matches at this point
if (num_matches == 0)
num_matches = target->GetImages().FindModules (module_spec, matching_module_list);
-
+
while (num_matches == 0)
{
ConstString filename_no_extension(module_spec.GetFileSpec().GetFileNameStrippingExtension());
// Empty string returned, lets bail
if (!filename_no_extension)
break;
-
+
// Check if there was no extension to strip and the basename is the same
if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
break;
-
+
// Replace basename with one less extension
module_spec.GetFileSpec().GetFilename() = filename_no_extension;
-
+
num_matches = target->GetImages().FindModules (module_spec, matching_module_list);
-
}
if (num_matches > 1)
@@ -4440,21 +4451,21 @@ protected:
else if (num_matches == 1)
{
ModuleSP module_sp (matching_module_list.GetModuleAtIndex(0));
-
+
// The module has not yet created its symbol vendor, we can just
// give the existing target module the symfile path to use for
// when it decides to create it!
module_sp->SetSymbolFileFileSpec (symbol_fspec);
-
+
SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(true, &result.GetErrorStream());
if (symbol_vendor)
{
SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
-
+
if (symbol_file)
{
ObjectFile *object_file = symbol_file->GetObjectFile();
-
+
if (object_file && object_file->GetFileSpec() == symbol_fspec)
{
// Provide feedback that the symfile has been successfully added.
@@ -4462,13 +4473,13 @@ protected:
result.AppendMessageWithFormat("symbol file '%s' has been added to '%s'\n",
symfile_path,
module_fs.GetPath().c_str());
-
+
// Let clients know something changed in the module
// if it is currently loaded
ModuleList module_list;
module_list.Append (module_sp);
target->SymbolsDidLoad (module_list);
-
+
// Make sure we load any scripting resources that may be embedded
// in the debug info files in case the platform supports that.
Error error;
@@ -4674,7 +4685,7 @@ protected:
if (platform_sp->ResolveSymbolFile(*target, module_spec, symfile_spec).Success())
module_spec.GetSymbolFileSpec() = symfile_spec;
}
-
+
ArchSpec arch;
bool symfile_exists = module_spec.GetSymbolFileSpec().Exists();
@@ -4710,13 +4721,11 @@ protected:
}
return result.Succeeded();
}
-
+
OptionGroupOptions m_option_group;
OptionGroupUUID m_uuid_option_group;
OptionGroupFile m_file_option;
OptionGroupBoolean m_current_frame_option;
-
-
};
@@ -4739,13 +4748,13 @@ public:
"target symbols <sub-command> ...")
{
LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetSymbolsAdd (interpreter)));
-
+
}
virtual
~CommandObjectTargetSymbols()
{
}
-
+
private:
//------------------------------------------------------------------
// For CommandObjectTargetModules only
@@ -4780,9 +4789,9 @@ public:
m_one_liner()
{
}
-
+
~CommandOptions () {}
-
+
const OptionDefinition*
GetDefinitions ()
{
@@ -4802,7 +4811,7 @@ public:
m_class_name = option_arg;
m_sym_ctx_specified = true;
break;
-
+
case 'e':
m_line_end = Args::StringToUInt32 (option_arg, UINT_MAX, 0, &success);
if (!success)
@@ -4812,7 +4821,7 @@ public:
}
m_sym_ctx_specified = true;
break;
-
+
case 'l':
m_line_start = Args::StringToUInt32 (option_arg, 0, 0, &success);
if (!success)
@@ -4822,17 +4831,17 @@ public:
}
m_sym_ctx_specified = true;
break;
-
+
case 'i':
m_no_inlines = true;
break;
-
+
case 'n':
m_function_name = option_arg;
m_func_name_type_mask |= eFunctionNameTypeAuto;
m_sym_ctx_specified = true;
break;
-
+
case 'f':
m_file_name = option_arg;
m_sym_ctx_specified = true;
@@ -4890,7 +4899,7 @@ public:
m_thread_index = UINT32_MAX;
m_thread_name.clear();
m_queue_name.clear();
-
+
m_no_inlines = false;
m_sym_ctx_specified = false;
m_thread_specified = false;
@@ -4899,9 +4908,9 @@ public:
m_one_liner.clear();
}
-
+
static OptionDefinition g_option_table[];
-
+
std::string m_class_name;
std::string m_function_name;
uint32_t m_line_start;
@@ -4942,7 +4951,6 @@ public:
}
protected:
-
virtual void
IOHandlerActivated (IOHandler &io_handler)
{
@@ -4953,8 +4961,7 @@ protected:
output_sp->Flush();
}
}
-
-
+
virtual void
IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
{
@@ -4986,12 +4993,12 @@ protected:
}
io_handler.SetIsDone(true);
}
-
+
bool
DoExecute (Args& command, CommandReturnObject &result)
{
m_stop_hook_sp.reset();
-
+
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target)
{
@@ -5002,63 +5009,63 @@ protected:
if (m_options.m_sym_ctx_specified)
{
specifier_ap.reset(new SymbolContextSpecifier(m_interpreter.GetDebugger().GetSelectedTarget()));
-
+
if (!m_options.m_module_name.empty())
{
specifier_ap->AddSpecification (m_options.m_module_name.c_str(), SymbolContextSpecifier::eModuleSpecified);
}
-
+
if (!m_options.m_class_name.empty())
{
specifier_ap->AddSpecification (m_options.m_class_name.c_str(), SymbolContextSpecifier::eClassOrNamespaceSpecified);
}
-
+
if (!m_options.m_file_name.empty())
{
specifier_ap->AddSpecification (m_options.m_file_name.c_str(), SymbolContextSpecifier::eFileSpecified);
}
-
+
if (m_options.m_line_start != 0)
{
specifier_ap->AddLineSpecification (m_options.m_line_start, SymbolContextSpecifier::eLineStartSpecified);
}
-
+
if (m_options.m_line_end != UINT_MAX)
{
specifier_ap->AddLineSpecification (m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
}
-
+
if (!m_options.m_function_name.empty())
{
specifier_ap->AddSpecification (m_options.m_function_name.c_str(), SymbolContextSpecifier::eFunctionSpecified);
}
}
-
+
if (specifier_ap.get())
new_hook_sp->SetSpecifier (specifier_ap.release());
// Next see if any of the thread options have been entered:
-
+
if (m_options.m_thread_specified)
{
ThreadSpec *thread_spec = new ThreadSpec();
-
+
if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
{
thread_spec->SetTID (m_options.m_thread_id);
}
-
+
if (m_options.m_thread_index != UINT32_MAX)
thread_spec->SetIndex (m_options.m_thread_index);
-
+
if (!m_options.m_thread_name.empty())
thread_spec->SetName (m_options.m_thread_name.c_str());
-
+
if (!m_options.m_queue_name.empty())
thread_spec->SetQueueName (m_options.m_queue_name.c_str());
-
+
new_hook_sp->SetThreadSpecifier (thread_spec);
-
+
}
if (m_options.m_use_one_liner)
{
@@ -5082,7 +5089,7 @@ protected:
result.AppendError ("invalid target\n");
result.SetStatus (eReturnStatusFailed);
}
-
+
return result.Succeeded();
}
private:
@@ -5093,29 +5100,29 @@ private:
OptionDefinition
CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOneLiner,
+ { LLDB_OPT_SET_ALL, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOneLiner,
"Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
- { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
+ { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
"Set the module within which the stop-hook is to be run."},
- { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadIndex,
+ { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex,
"The stop hook is run only for the thread whose index matches this argument."},
- { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadID,
+ { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadID,
"The stop hook is run only for the thread whose TID matches this argument."},
- { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadName,
+ { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadName,
"The stop hook is run only for the thread whose thread name matches this argument."},
- { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, NULL, 0, eArgTypeQueueName,
+ { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeQueueName,
"The stop hook is run only for threads in the queue whose name is given by this argument."},
- { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
"Specify the source file within which the stop-hook is to be run." },
- { LLDB_OPT_SET_1, false, "start-line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum,
+ { LLDB_OPT_SET_1, false, "start-line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
"Set the start of the line range for which the stop-hook is to be run."},
- { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum,
+ { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
"Set the end of the line range for which the stop-hook is to be run."},
- { LLDB_OPT_SET_2, false, "classname", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeClassName,
+ { LLDB_OPT_SET_2, false, "classname", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeClassName,
"Specify the class within which the stop-hook is to be run." },
- { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
+ { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
"Set the function name within which the stop hook will be run." },
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#pragma mark CommandObjectTargetStopHookDelete
@@ -5189,7 +5196,7 @@ protected:
result.AppendError ("invalid target\n");
result.SetStatus (eReturnStatusFailed);
}
-
+
return result.Succeeded();
}
};
@@ -5226,7 +5233,7 @@ protected:
// FIXME: see if we can use the breakpoint id style parser?
size_t num_args = command.GetArgumentCount();
bool success;
-
+
if (num_args == 0)
{
target->SetAllStopHooksActiveState (m_enable);
@@ -5297,7 +5304,7 @@ protected:
result.SetStatus (eReturnStatusFailed);
return result.Succeeded();
}
-
+
size_t num_hooks = target->GetNumStopHooks ();
if (num_hooks == 0)
{
@@ -5367,7 +5374,7 @@ CommandObjectMultiwordTarget::CommandObjectMultiwordTarget (CommandInterpreter &
"A set of commands for operating on debugger targets.",
"target <subcommand> [<subcommand-options>]")
{
-
+
LoadSubCommand ("create", CommandObjectSP (new CommandObjectTargetCreate (interpreter)));
LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTargetDelete (interpreter)));
LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetList (interpreter)));
diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp
index 10d661882c92..e7a8652ac898 100644
--- a/source/Commands/CommandObjectThread.cpp
+++ b/source/Commands/CommandObjectThread.cpp
@@ -305,10 +305,10 @@ protected:
OptionDefinition
CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
-{ LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
-{ LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Show the extended backtrace, if available"},
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
+{ LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
+{ LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Show the extended backtrace, if available"},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
enum StepScope
@@ -348,12 +348,37 @@ public:
case 'a':
{
bool success;
- m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success);
+ bool avoid_no_debug = Args::StringToBoolean (option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
+ else
+ {
+ m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
+ }
+ }
+ break;
+
+ case 'A':
+ {
+ bool success;
+ bool avoid_no_debug = Args::StringToBoolean (option_arg, true, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
+ else
+ {
+ m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
+ }
}
break;
+ case 'c':
+ {
+ m_step_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
+ if (m_step_count == UINT32_MAX)
+ error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
+ break;
+ }
+ break;
case 'm':
{
OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
@@ -386,10 +411,12 @@ public:
void
OptionParsingStarting ()
{
- m_avoid_no_debug = true;
+ m_step_in_avoid_no_debug = eLazyBoolCalculate;
+ m_step_out_avoid_no_debug = eLazyBoolCalculate;
m_run_mode = eOnlyDuringStepping;
m_avoid_regexp.clear();
m_step_in_target.clear();
+ m_step_count = 1;
}
const OptionDefinition*
@@ -403,10 +430,12 @@ public:
static OptionDefinition g_option_table[];
// Instance variables to hold the values for command options.
- bool m_avoid_no_debug;
+ LazyBool m_step_in_avoid_no_debug;
+ LazyBool m_step_out_avoid_no_debug;
RunMode m_run_mode;
std::string m_avoid_regexp;
std::string m_step_in_target;
+ int32_t m_step_count;
};
CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
@@ -522,7 +551,9 @@ protected:
frame->GetSymbolContext(eSymbolContextEverything),
m_options.m_step_in_target.c_str(),
stop_other_threads,
- m_options.m_avoid_no_debug);
+ m_options.m_step_in_avoid_no_debug,
+ m_options.m_step_out_avoid_no_debug);
+
if (new_plan_sp && !m_options.m_avoid_regexp.empty())
{
ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get());
@@ -541,7 +572,8 @@ protected:
new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
frame->GetSymbolContext(eSymbolContextEverything),
- stop_other_threads);
+ stop_other_threads,
+ m_options.m_step_out_avoid_no_debug);
else
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true,
abort_other_plans,
@@ -564,7 +596,8 @@ protected:
bool_stop_other_threads,
eVoteYes,
eVoteNoOpinion,
- thread->GetSelectedFrameIndex());
+ thread->GetSelectedFrameIndex(),
+ m_options.m_step_out_avoid_no_debug);
}
else
{
@@ -580,10 +613,22 @@ protected:
{
new_plan_sp->SetIsMasterPlan (true);
new_plan_sp->SetOkayToDiscard (false);
+
+ if (m_options.m_step_count > 1)
+ {
+ if (new_plan_sp->SetIterationCount(m_options.m_step_count))
+ {
+ result.AppendWarning ("step operation does not support iteration count.");
+ }
+ }
process->GetThreadList().SetSelectedThreadByID (thread->GetID());
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
+ // a chance to call PushProcessIOHandler().
+ process->SyncIOHandler(2000);
if (synchronous_execution)
{
@@ -639,11 +684,13 @@ g_duo_running_mode[] =
OptionDefinition
CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "avoid-no-debug", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether step-in will step over functions with no debug information."},
-{ LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, 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, 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, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."},
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ 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."},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -770,8 +817,9 @@ public:
result.AppendMessageWithFormat ("%u, ", thread->GetIndexID());
else
result.AppendMessageWithFormat ("%u ", thread->GetIndexID());
-
- thread->SetResumeState (eStateRunning);
+
+ const bool override_suspend = true;
+ thread->SetResumeState (eStateRunning, override_suspend);
}
else
{
@@ -802,7 +850,8 @@ public:
if (thread == current_thread)
{
result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID());
- thread->SetResumeState (eStateRunning);
+ const bool override_suspend = true;
+ thread->SetResumeState (eStateRunning, override_suspend);
}
else
{
@@ -1177,10 +1226,10 @@ protected:
OptionDefinition
CommandObjectThreadUntil::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"},
-{ LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"},
-{ LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"},
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"},
+{ LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"},
+{ LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, NULL, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -1306,6 +1355,193 @@ protected:
};
//-------------------------------------------------------------------------
+// CommandObjectThreadInfo
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadInfo : public CommandObjectParsed
+{
+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),
+ 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);
+ }
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options (interpreter)
+ {
+ OptionParsingStarting ();
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_json = false;
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg)
+ {
+ const int short_option = m_getopt_table[option_idx].val;
+ Error error;
+
+ switch (short_option)
+ {
+ case 'j':
+ m_json = true;
+ break;
+
+ default:
+ return Error("invalid short option character '%c'", short_option);
+
+ }
+ return error;
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ bool m_json;
+
+ static OptionDefinition g_option_table[];
+ };
+
+ virtual
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+
+ virtual
+ ~CommandObjectThreadInfo ()
+ {
+ }
+
+ virtual bool
+ DoExecute (Args& command, 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
+ {
+ const size_t num_args = command.GetArgumentCount();
+ Process *process = m_exe_ctx.GetProcessPtr();
+ Mutex::Locker locker (process->GetThreadList().GetMutex());
+ std::vector<ThreadSP> 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("");
+ }
+
+ }
+ return result.Succeeded();
+ }
+
+ CommandOptions m_options;
+
+};
+
+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."},
+
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+
+//-------------------------------------------------------------------------
// CommandObjectThreadReturn
//-------------------------------------------------------------------------
@@ -1477,12 +1713,12 @@ protected:
options.SetUnwindOnError(true);
options.SetUseDynamic(eNoDynamicValues);
- ExecutionResults exe_results = eExecutionSetupError;
+ ExpressionResults exe_results = eExpressionSetupError;
exe_results = target->EvaluateExpression (command,
frame_sp.get(),
return_valobj_sp,
options);
- if (exe_results != eExecutionCompleted)
+ if (exe_results != eExpressionCompleted)
{
if (return_valobj_sp)
result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString());
@@ -1515,8 +1751,8 @@ protected:
OptionDefinition
CommandObjectThreadReturn::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Return from the innermost expression evaluation."},
-{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Return from the innermost expression evaluation."},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -1702,23 +1938,23 @@ protected:
OptionDefinition
CommandObjectThreadJump::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
"Specifies the source file to jump to."},
- { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum,
+ { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
"Specifies the line number to jump to."},
- { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset,
+ { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset,
"Jumps by a relative line offset from the current line."},
- { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression,
+ { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression,
"Jumps to a specific address."},
{ LLDB_OPT_SET_1|
LLDB_OPT_SET_2|
- LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."},
+ LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -1738,6 +1974,7 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
LoadSubCommand ("jump", CommandObjectSP (new CommandObjectThreadJump (interpreter)));
LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
+ LoadSubCommand ("info", CommandObjectSP (new CommandObjectThreadInfo (interpreter)));
LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
interpreter,
"thread step-in",
diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp
index f1b1d2c1900c..640fd6dd3fa4 100644
--- a/source/Commands/CommandObjectType.cpp
+++ b/source/Commands/CommandObjectType.cpp
@@ -17,6 +17,8 @@
// C++ Includes
+#include "llvm/ADT/StringRef.h"
+
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/IOHandler.h"
@@ -98,7 +100,7 @@ public:
static bool
WarnOnPotentialUnquotedUnsignedType (Args& command, CommandReturnObject &result)
{
- for (int idx = 0; idx < command.GetArgumentCount(); idx++)
+ for (unsigned idx = 0; idx < command.GetArgumentCount(); idx++)
{
const char* arg = command.GetArgumentAtIndex(idx);
if (idx+1 < command.GetArgumentCount())
@@ -204,7 +206,7 @@ public:
static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
"def function (valobj,internal_dict):\n"
" \"\"\"valobj: an SBValue which you want to provide a summary for\n"
- " internal_dict: an LLDB support object not to be used\"\"\"";
+ " internal_dict: an LLDB support object not to be used\"\"\"\n";
StreamFileSP output_sp(io_handler.GetOutputStreamFile());
if (output_sp)
@@ -876,13 +878,13 @@ protected:
OptionDefinition
CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
- { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Format variables as if they were of this type."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
+ { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
+ { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
+ { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
+ { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
+ { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Format variables as if they were of this type."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -1054,9 +1056,9 @@ protected:
OptionDefinition
CommandObjectTypeFormatDelete::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Delete from every category."},
- { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Delete from given category."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."},
+ { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -1182,8 +1184,8 @@ protected:
OptionDefinition
CommandObjectTypeFormatClear::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Clear every category."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -1395,8 +1397,8 @@ CommandObjectTypeRXFormatList_LoopCallback (
OptionDefinition
CommandObjectTypeFormatList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#ifndef LLDB_DISABLE_PYTHON
@@ -1814,6 +1816,25 @@ CommandObjectTypeSummaryAdd::DoExecute (Args& command, CommandReturnObject &resu
return Execute_StringSummary(command, result);
}
+static bool
+FixArrayTypeNameWithRegex (ConstString &type_name)
+{
+ llvm::StringRef type_name_ref(type_name.GetStringRef());
+
+ if (type_name_ref.endswith("[]"))
+ {
+ std::string type_name_str(type_name.GetCString());
+ type_name_str.resize(type_name_str.length()-2);
+ if (type_name_str.back() != ' ')
+ type_name_str.append(" \\[[0-9]+\\]");
+ else
+ type_name_str.append("\\[[0-9]+\\]");
+ type_name.SetCString(type_name_str.c_str());
+ return true;
+ }
+ return false;
+}
+
bool
CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
TypeSummaryImplSP entry,
@@ -1826,17 +1847,8 @@ CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
if (type == eRegularSummary)
{
- std::string type_name_str(type_name.GetCString());
- if (type_name_str.compare(type_name_str.length() - 2, 2, "[]") == 0)
- {
- type_name_str.resize(type_name_str.length()-2);
- if (type_name_str.back() != ' ')
- type_name_str.append(" \\[[0-9]+\\]");
- else
- type_name_str.append("\\[[0-9]+\\]");
- type_name.SetCString(type_name_str.c_str());
+ if (FixArrayTypeNameWithRegex (type_name))
type = eRegexSummary;
- }
}
if (type == eRegexSummary)
@@ -1870,21 +1882,21 @@ CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
OptionDefinition
CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
- { LLDB_OPT_SET_ALL, false, "no-value", 'v', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type."},
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
- { LLDB_OPT_SET_1 , true, "inline-children", 'c', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "If true, inline all child values into summary string."},
- { LLDB_OPT_SET_1 , false, "omit-names", 'O', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "If true, omit value names in the summary display."},
- { LLDB_OPT_SET_2 , true, "summary-string", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeSummaryString, "Summary string used to display text and object contents."},
- { LLDB_OPT_SET_3, false, "python-script", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command."},
- { LLDB_OPT_SET_3, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type."},
- { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."},
- { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines."},
- { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "A name for this summary string."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
+ { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
+ { LLDB_OPT_SET_ALL, false, "no-value", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type."},
+ { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
+ { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
+ { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
+ { LLDB_OPT_SET_1 , true, "inline-children", 'c', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "If true, inline all child values into summary string."},
+ { LLDB_OPT_SET_1 , false, "omit-names", 'O', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "If true, omit value names in the summary display."},
+ { LLDB_OPT_SET_2 , true, "summary-string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeSummaryString, "Summary string used to display text and object contents."},
+ { LLDB_OPT_SET_3, false, "python-script", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command."},
+ { LLDB_OPT_SET_3, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type."},
+ { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."},
+ { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines."},
+ { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "A name for this summary string."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -2049,9 +2061,9 @@ protected:
OptionDefinition
CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Delete from every category."},
- { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Delete from given category."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."},
+ { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
class CommandObjectTypeSummaryClear : public CommandObjectParsed
@@ -2176,8 +2188,8 @@ protected:
OptionDefinition
CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Clear every category."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -2405,8 +2417,8 @@ CommandObjectTypeRXSummaryList_LoopCallback (
OptionDefinition
CommandObjectTypeSummaryList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -2953,8 +2965,8 @@ CommandObjectTypeFilterRXList_LoopCallback (void* pt2self,
OptionDefinition
CommandObjectTypeFilterList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#ifndef LLDB_DISABLE_PYTHON
@@ -3168,8 +3180,8 @@ CommandObjectTypeSynthRXList_LoopCallback (void* pt2self,
OptionDefinition
CommandObjectTypeSynthList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#endif // #ifndef LLDB_DISABLE_PYTHON
@@ -3332,9 +3344,9 @@ protected:
OptionDefinition
CommandObjectTypeFilterDelete::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Delete from every category."},
- { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Delete from given category."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."},
+ { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#ifndef LLDB_DISABLE_PYTHON
@@ -3498,9 +3510,9 @@ protected:
OptionDefinition
CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Delete from every category."},
- { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Delete from given category."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."},
+ { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#endif // #ifndef LLDB_DISABLE_PYTHON
@@ -3629,8 +3641,8 @@ protected:
OptionDefinition
CommandObjectTypeFilterClear::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Clear every category."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#ifndef LLDB_DISABLE_PYTHON
@@ -3758,8 +3770,8 @@ protected:
OptionDefinition
CommandObjectTypeSynthClear::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Clear every category."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -3897,17 +3909,8 @@ CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
if (type == eRegularSynth)
{
- std::string type_name_str(type_name.GetCString());
- if (type_name_str.compare(type_name_str.length() - 2, 2, "[]") == 0)
- {
- type_name_str.resize(type_name_str.length()-2);
- if (type_name_str.back() != ' ')
- type_name_str.append(" \\[[0-9]+\\]");
- else
- type_name_str.append("\\[[0-9]+\\]");
- type_name.SetCString(type_name_str.c_str());
- type = eRegularSynth;
- }
+ if (FixArrayTypeNameWithRegex (type_name))
+ type = eRegexSynth;
}
if (category->AnyMatches(type_name,
@@ -3944,14 +3947,14 @@ CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
OptionDefinition
CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
- { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."},
- { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."},
- { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
+ { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
+ { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for references-to-tNULL, ype objects."},
+ { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
+ { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."},
+ { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument,NULL, NULL, 0, eArgTypeNone, "Type Python code to generate a class that NULL, provides synthetic children."},
+ { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#endif // #ifndef LLDB_DISABLE_PYTHON
@@ -4076,17 +4079,8 @@ private:
if (type == eRegularFilter)
{
- std::string type_name_str(type_name.GetCString());
- if (type_name_str.compare(type_name_str.length() - 2, 2, "[]") == 0)
- {
- type_name_str.resize(type_name_str.length()-2);
- if (type_name_str.back() != ' ')
- type_name_str.append(" \\[[0-9]+\\]");
- else
- type_name_str.append("\\[[0-9]+\\]");
- type_name.SetCString(type_name_str.c_str());
+ if (FixArrayTypeNameWithRegex (type_name))
type = eRegexFilter;
- }
}
if (category->AnyMatches(type_name,
@@ -4250,13 +4244,13 @@ protected:
OptionDefinition
CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
- { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view."},
- { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
+ { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
+ { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
+ { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
+ { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view."},
+ { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
class CommandObjectTypeFormat : public CommandObjectMultiword
diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp
index e55b2ee4d7d8..ca5fe98ccb31 100644
--- a/source/Commands/CommandObjectWatchpoint.cpp
+++ b/source/Commands/CommandObjectWatchpoint.cpp
@@ -28,6 +28,8 @@
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Target.h"
+#include "llvm/ADT/StringRef.h"
+
#include <vector>
using namespace lldb;
@@ -62,14 +64,6 @@ CheckTargetForWatchpointOperations(Target *target, CommandReturnObject &result)
return true;
}
-// FIXME: This doesn't seem to be the right place for this functionality.
-#include "llvm/ADT/StringRef.h"
-static inline void StripLeadingSpaces(llvm::StringRef &Str)
-{
- while (!Str.empty() && isspace(Str[0]))
- Str = Str.substr(1);
-}
-
// Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
static const char* RSA[4] = { "-", "to", "To", "TO" };
@@ -335,16 +329,16 @@ private:
OptionDefinition
CommandObjectWatchpointList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Give a brief description of the watchpoint (no location info)."},
- { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Give a full description of the watchpoint and its locations."},
- { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Explain everything we know about the watchpoint (for debugging debugger bugs)." },
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -397,7 +391,7 @@ protected:
{
// No watchpoint selected; enable all currently set watchpoints.
target->EnableAllWatchpoints();
- result.AppendMessageWithFormat("All watchpoints enabled. (%zu watchpoints)\n", num_watchpoints);
+ result.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64 " watchpoints)\n", (uint64_t)num_watchpoints);
result.SetStatus(eReturnStatusSuccessFinishNoResult);
}
else
@@ -476,7 +470,7 @@ protected:
// No watchpoint selected; disable all currently set watchpoints.
if (target->DisableAllWatchpoints())
{
- result.AppendMessageWithFormat("All watchpoints disabled. (%zu watchpoints)\n", num_watchpoints);
+ result.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64 " watchpoints)\n", (uint64_t)num_watchpoints);
result.SetStatus(eReturnStatusSuccessFinishNoResult);
}
else
@@ -564,7 +558,7 @@ protected:
else
{
target->RemoveAllWatchpoints();
- result.AppendMessageWithFormat("All watchpoints removed. (%zu watchpoints)\n", num_watchpoints);
+ result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64 " watchpoints)\n", (uint64_t)num_watchpoints);
}
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
@@ -706,7 +700,7 @@ protected:
if (command.GetArgumentCount() == 0)
{
target->IgnoreAllWatchpoints(m_options.m_ignore_count);
- result.AppendMessageWithFormat("All watchpoints ignored. (%zu watchpoints)\n", num_watchpoints);
+ result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64 " watchpoints)\n", (uint64_t)num_watchpoints);
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
@@ -740,8 +734,8 @@ private:
OptionDefinition
CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." },
- { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." },
+ { 0, false, NULL, 0 , 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -903,8 +897,8 @@ private:
OptionDefinition
CommandObjectWatchpointModify::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."},
-{ 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
+{ LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."},
+{ 0, false, NULL, 0 , 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
@@ -1099,8 +1093,8 @@ protected:
}
else
{
- result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%zu, variable expression='%s').\n",
- addr, size, command.GetArgumentAtIndex(0));
+ result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64 ", variable expression='%s').\n",
+ addr, (uint64_t)size, command.GetArgumentAtIndex(0));
if (error.AsCString(NULL))
result.AppendError(error.AsCString());
result.SetStatus(eReturnStatusFailed);
@@ -1262,11 +1256,11 @@ protected:
options.SetTryAllThreads(true);
options.SetTimeoutUsec(0);
- ExecutionResults expr_result = target->EvaluateExpression (expr,
+ ExpressionResults expr_result = target->EvaluateExpression (expr,
frame,
valobj_sp,
options);
- if (expr_result != eExecutionCompleted)
+ if (expr_result != eExpressionCompleted)
{
result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n");
result.GetErrorStream().Printf("expression evaluated: %s\n", expr);
@@ -1308,8 +1302,8 @@ protected:
}
else
{
- result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%zu).\n",
- addr, size);
+ result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64 ").\n",
+ addr, (uint64_t)size);
if (error.AsCString(NULL))
result.AppendError(error.AsCString());
result.SetStatus(eReturnStatusFailed);
diff --git a/source/Commands/CommandObjectWatchpointCommand.cpp b/source/Commands/CommandObjectWatchpointCommand.cpp
index 0083ff140e5a..f46db7a6a82b 100644
--- a/source/Commands/CommandObjectWatchpointCommand.cpp
+++ b/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -519,19 +519,19 @@ g_script_option_enumeration[4] =
OptionDefinition
CommandObjectWatchpointCommandAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOneLiner,
+ { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOneLiner,
"Specify a one-line watchpoint command inline. Be sure to surround it with quotes." },
- { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
+ { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
"Specify whether watchpoint command execution should terminate on error." },
- { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, g_script_option_enumeration, 0, eArgTypeNone,
+ { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, NULL, g_script_option_enumeration, 0, eArgTypeNone,
"Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
- { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, 0, eArgTypePythonFunction,
+ { 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 watchpoint. Be sure to give a module name if appropriate."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp
index 5ac2bcce70f0..fa9197d12b70 100644
--- a/source/Core/Address.cpp
+++ b/source/Core/Address.cpp
@@ -427,7 +427,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
break;
case DumpStyleSectionPointerOffset:
- s->Printf("(Section *)%p + ", section_sp.get());
+ s->Printf("(Section *)%p + ", static_cast<void*>(section_sp.get()));
s->Address(m_offset, addr_size);
break;
diff --git a/source/Core/AddressRange.cpp b/source/Core/AddressRange.cpp
index 835a01d82aa4..3505d56b43e2 100644
--- a/source/Core/AddressRange.cpp
+++ b/source/Core/AddressRange.cpp
@@ -196,7 +196,10 @@ AddressRange::Dump(Stream *s, Target *target, Address::DumpStyle style, Address:
void
AddressRange::DumpDebug (Stream *s) const
{
- s->Printf("%p: AddressRange section = %p, offset = 0x%16.16" PRIx64 ", byte_size = 0x%16.16" PRIx64 "\n", this, m_base_addr.GetSection().get(), m_base_addr.GetOffset(), GetByteSize());
+ s->Printf("%p: AddressRange section = %p, offset = 0x%16.16" PRIx64 ", byte_size = 0x%16.16" PRIx64 "\n",
+ static_cast<const void*>(this),
+ static_cast<void*>(m_base_addr.GetSection().get()),
+ m_base_addr.GetOffset(), GetByteSize());
}
//
//bool
diff --git a/source/Core/AddressResolverName.cpp b/source/Core/AddressResolverName.cpp
index dd22e17402ba..9f3b3f506fe0 100644
--- a/source/Core/AddressResolverName.cpp
+++ b/source/Core/AddressResolverName.cpp
@@ -148,7 +148,7 @@ AddressResolverName::SearchCallback
break;
}
- // Remove any duplicates between the funcion list and the symbol list
+ // Remove any duplicates between the function list and the symbol list
if (func_list.GetSize())
{
for (i = 0; i < func_list.GetSize(); i++)
diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp
index a93f4bd7b5f7..5f010f066408 100644
--- a/source/Core/ArchSpec.cpp
+++ b/source/Core/ArchSpec.cpp
@@ -14,13 +14,15 @@
#include <string>
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/MachO.h"
+#include "lldb/Utility/SafeMachO.h"
#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/StringList.h"
#include "lldb/Host/Endian.h"
-#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Platform.h"
using namespace lldb;
@@ -41,13 +43,13 @@ namespace lldb_private {
uint32_t max_opcode_byte_size;
llvm::Triple::ArchType machine;
ArchSpec::Core core;
- const char *name;
+ const char * const name;
};
}
// This core information can be looked using the ArchSpec::Core as the index
-static const CoreDefinition g_core_definitions[ArchSpec::kNumCores] =
+static const CoreDefinition g_core_definitions[] =
{
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_generic , "arm" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv4 , "armv4" },
@@ -76,6 +78,9 @@ static const CoreDefinition g_core_definitions[ArchSpec::kNumCores] =
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv7k , "thumbv7k" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv7m , "thumbv7m" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv7em , "thumbv7em" },
+ { eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_arm64 , "arm64" },
+ { eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_armv8 , "armv8" },
+ { eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_aarch64 , "aarch64" },
{ eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64 , "mips64" },
@@ -102,6 +107,7 @@ static const CoreDefinition g_core_definitions[ArchSpec::kNumCores] =
{ eByteOrderLittle, 4, 1, 15, llvm::Triple::x86 , ArchSpec::eCore_x86_32_i386 , "i386" },
{ eByteOrderLittle, 4, 1, 15, llvm::Triple::x86 , ArchSpec::eCore_x86_32_i486 , "i486" },
{ eByteOrderLittle, 4, 1, 15, llvm::Triple::x86 , ArchSpec::eCore_x86_32_i486sx , "i486sx" },
+ { eByteOrderLittle, 4, 1, 15, llvm::Triple::x86 , ArchSpec::eCore_x86_32_i686 , "i686" },
{ eByteOrderLittle, 8, 1, 15, llvm::Triple::x86_64 , ArchSpec::eCore_x86_64_x86_64 , "x86_64" },
{ eByteOrderLittle, 8, 1, 15, llvm::Triple::x86_64 , ArchSpec::eCore_x86_64_x86_64h , "x86_64h" },
@@ -110,9 +116,19 @@ static const CoreDefinition g_core_definitions[ArchSpec::kNumCores] =
{ eByteOrderLittle, 4, 4, 4, llvm::Triple::hexagon , ArchSpec::eCore_hexagon_hexagonv5, "hexagonv5" },
{ 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, 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" }
};
+// Ensure that we have an entry in the g_core_definitions for each core. If you comment out an entry above,
+// you will need to comment out the corresponding ArchSpec::Core enumeration.
+static_assert(sizeof(g_core_definitions) / sizeof(CoreDefinition) == ArchSpec::kNumCores, "make sure we have one core definition for each core");
+
+
struct ArchDefinitionEntry
{
ArchSpec::Core core;
@@ -137,7 +153,7 @@ ArchSpec::AutoComplete (const char *name, StringList &matches)
uint32_t i;
if (name && name[0])
{
- for (i = 0; i < ArchSpec::kNumCores; ++i)
+ for (i = 0; i < llvm::array_lengthof(g_core_definitions); ++i)
{
if (NameMatches(g_core_definitions[i].name, eNameMatchStartsWith, name))
matches.AppendString (g_core_definitions[i].name);
@@ -145,7 +161,7 @@ ArchSpec::AutoComplete (const char *name, StringList &matches)
}
else
{
- for (i = 0; i < ArchSpec::kNumCores; ++i)
+ for (i = 0; i < llvm::array_lengthof(g_core_definitions); ++i)
matches.AppendString (g_core_definitions[i].name);
}
return matches.GetSize();
@@ -179,6 +195,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 , 13 , 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 },
@@ -221,7 +241,7 @@ static const ArchDefinitionEntry g_macho_arch_entries[] =
};
static const ArchDefinition g_macho_arch_def = {
eArchTypeMachO,
- sizeof(g_macho_arch_entries)/sizeof(g_macho_arch_entries[0]),
+ llvm::array_lengthof(g_macho_arch_entries),
g_macho_arch_entries,
"mach-o"
};
@@ -239,33 +259,39 @@ static const ArchDefinitionEntry g_elf_arch_entries[] =
{ ArchSpec::eCore_ppc_generic , llvm::ELF::EM_PPC , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // PowerPC
{ ArchSpec::eCore_ppc64_generic , llvm::ELF::EM_PPC64 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // PowerPC64
{ ArchSpec::eCore_arm_generic , llvm::ELF::EM_ARM , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARM
+ { ArchSpec::eCore_arm_aarch64 , llvm::ELF::EM_AARCH64, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARM64
{ ArchSpec::eCore_sparc9_generic , llvm::ELF::EM_SPARCV9, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // SPARC V9
{ 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_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
+
};
static const ArchDefinition g_elf_arch_def = {
eArchTypeELF,
- sizeof(g_elf_arch_entries)/sizeof(g_elf_arch_entries[0]),
+ llvm::array_lengthof(g_elf_arch_entries),
g_elf_arch_entries,
"elf",
};
static const ArchDefinitionEntry g_coff_arch_entries[] =
{
- { ArchSpec::eCore_x86_32_i386 , llvm::COFF::IMAGE_FILE_MACHINE_I386 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // Intel 80386
+ { ArchSpec::eCore_x86_32_i386 , llvm::COFF::IMAGE_FILE_MACHINE_I386 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // Intel 80x86
{ ArchSpec::eCore_ppc_generic , llvm::COFF::IMAGE_FILE_MACHINE_POWERPC , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // PowerPC
{ ArchSpec::eCore_ppc_generic , llvm::COFF::IMAGE_FILE_MACHINE_POWERPCFP, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // PowerPC (with FPU)
{ ArchSpec::eCore_arm_generic , llvm::COFF::IMAGE_FILE_MACHINE_ARM , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARM
- { ArchSpec::eCore_arm_armv7 , llvm::COFF::IMAGE_FILE_MACHINE_ARMV7 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARMv7
+ { ArchSpec::eCore_arm_armv7 , llvm::COFF::IMAGE_FILE_MACHINE_ARMNT , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARMv7
{ ArchSpec::eCore_thumb , llvm::COFF::IMAGE_FILE_MACHINE_THUMB , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARMv7
{ ArchSpec::eCore_x86_64_x86_64, llvm::COFF::IMAGE_FILE_MACHINE_AMD64 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu } // AMD64
};
static const ArchDefinition g_coff_arch_def = {
eArchTypeCOFF,
- sizeof(g_coff_arch_entries)/sizeof(g_coff_arch_entries[0]),
+ llvm::array_lengthof(g_coff_arch_entries),
g_coff_arch_entries,
"pe-coff",
};
@@ -278,8 +304,7 @@ static const ArchDefinition *g_arch_definitions[] = {
&g_coff_arch_def
};
-static const size_t k_num_arch_definitions =
- sizeof(g_arch_definitions) / sizeof(g_arch_definitions[0]);
+static const size_t k_num_arch_definitions = llvm::array_lengthof(g_arch_definitions);
//===----------------------------------------------------------------------===//
// Static helper functions.
@@ -302,7 +327,7 @@ FindArchDefinition (ArchitectureType arch_type)
static const CoreDefinition *
FindCoreDefinition (llvm::StringRef name)
{
- for (unsigned int i = 0; i < ArchSpec::kNumCores; ++i)
+ for (unsigned int i = 0; i < llvm::array_lengthof(g_core_definitions); ++i)
{
if (name.equals_lower(g_core_definitions[i].name))
return &g_core_definitions[i];
@@ -313,7 +338,7 @@ FindCoreDefinition (llvm::StringRef name)
static inline const CoreDefinition *
FindCoreDefinition (ArchSpec::Core core)
{
- if (core >= 0 && core < ArchSpec::kNumCores)
+ if (core >= 0 && core < llvm::array_lengthof(g_core_definitions))
return &g_core_definitions[core];
return NULL;
}
@@ -472,6 +497,40 @@ ArchSpec::GetMachOCPUSubType () const
return LLDB_INVALID_CPUTYPE;
}
+uint32_t
+ArchSpec::GetDataByteSize () const
+{
+ switch (m_core)
+ {
+ case eCore_kalimba3:
+ return 3;
+ case eCore_kalimba4:
+ return 1;
+ case eCore_kalimba5:
+ return 3;
+ default:
+ return 1;
+ }
+ return 1;
+}
+
+uint32_t
+ArchSpec::GetCodeByteSize () const
+{
+ switch (m_core)
+ {
+ case eCore_kalimba3:
+ return 4;
+ case eCore_kalimba4:
+ return 1;
+ case eCore_kalimba5:
+ return 1;
+ default:
+ return 1;
+ }
+ return 1;
+}
+
llvm::Triple::ArchType
ArchSpec::GetMachine () const
{
@@ -605,11 +664,11 @@ ArchSpec::SetTriple (const char *triple_cstr)
{
// Special case for the current host default architectures...
if (triple_stref.equals (LLDB_ARCH_DEFAULT_32BIT))
- *this = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
+ *this = HostInfo::GetArchitecture(HostInfo::eArchKind32);
else if (triple_stref.equals (LLDB_ARCH_DEFAULT_64BIT))
- *this = Host::GetArchitecture (Host::eSystemDefaultArchitecture64);
+ *this = HostInfo::GetArchitecture(HostInfo::eArchKind64);
else if (triple_stref.equals (LLDB_ARCH_DEFAULT))
- *this = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
+ *this = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
}
else
{
@@ -636,11 +695,11 @@ ArchSpec::SetTriple (const char *triple_cstr, Platform *platform)
{
// Special case for the current host default architectures...
if (triple_stref.equals (LLDB_ARCH_DEFAULT_32BIT))
- *this = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
+ *this = HostInfo::GetArchitecture(HostInfo::eArchKind32);
else if (triple_stref.equals (LLDB_ARCH_DEFAULT_64BIT))
- *this = Host::GetArchitecture (Host::eSystemDefaultArchitecture64);
+ *this = HostInfo::GetArchitecture(HostInfo::eArchKind64);
else if (triple_stref.equals (LLDB_ARCH_DEFAULT))
- *this = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
+ *this = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
}
else
{
@@ -729,6 +788,7 @@ ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t su
switch (core_def->machine)
{
+ case llvm::Triple::aarch64:
case llvm::Triple::arm:
case llvm::Triple::thumb:
m_triple.setOS (llvm::Triple::IOS);
@@ -736,6 +796,15 @@ ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t su
case llvm::Triple::x86:
case llvm::Triple::x86_64:
+ // Don't set the OS for x86_64 or for x86 as we want to leave it as an "unspecified unknown"
+ // which means if we ask for the OS from the llvm::Triple we get back llvm::Triple::UnknownOS, but
+ // if we ask for the string value for the OS it will come back empty (unspecified).
+ // We do this because we now have iOS and MacOSX as the OS values for x86 and x86_64 for
+ // normal desktop and simulator binaries. And if we compare a "x86_64-apple-ios" to a "x86_64-apple-"
+ // triple, it will say it is compatible (because the OS is unspecified in the second one and will match
+ // anything in the first
+ break;
+
default:
m_triple.setOS (llvm::Triple::MacOSX);
break;
@@ -837,6 +906,7 @@ ArchSpec::IsEqualTo (const ArchSpec& rhs, bool exact_match) const
if (rhs_os_specified && lhs_os_specified)
return false;
}
+
// Only fail if both os types are not unknown
if (lhs_triple_os != llvm::Triple::UnknownOS &&
rhs_triple_os != llvm::Triple::UnknownOS)
@@ -893,6 +963,10 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
case ArchSpec::kCore_any:
return true;
+ case ArchSpec::eCore_arm_generic:
+ if (enforce_exact_match)
+ break;
+ // Fall through to case below
case ArchSpec::kCore_arm_any:
if (core2 >= ArchSpec::kCore_arm_first && core2 <= ArchSpec::kCore_arm_last)
return true;
@@ -901,17 +975,22 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
if (core2 == ArchSpec::kCore_arm_any)
return true;
break;
-
+
case ArchSpec::kCore_x86_32_any:
if ((core2 >= ArchSpec::kCore_x86_32_first && core2 <= ArchSpec::kCore_x86_32_last) || (core2 == ArchSpec::kCore_x86_32_any))
return true;
break;
-
+
+ case ArchSpec::kCore_x86_64_any:
+ if ((core2 >= ArchSpec::kCore_x86_64_first && core2 <= ArchSpec::kCore_x86_64_last) || (core2 == ArchSpec::kCore_x86_64_any))
+ return true;
+ break;
+
case ArchSpec::kCore_ppc_any:
if ((core2 >= ArchSpec::kCore_ppc_first && core2 <= ArchSpec::kCore_ppc_last) || (core2 == ArchSpec::kCore_ppc_any))
return true;
break;
-
+
case ArchSpec::kCore_ppc64_any:
if ((core2 >= ArchSpec::kCore_ppc64_first && core2 <= ArchSpec::kCore_ppc64_last) || (core2 == ArchSpec::kCore_ppc64_any))
return true;
@@ -920,10 +999,13 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
case ArchSpec::eCore_arm_armv6m:
if (!enforce_exact_match)
{
+ if (core2 == ArchSpec::eCore_arm_generic)
+ return true;
try_inverse = false;
if (core2 == ArchSpec::eCore_arm_armv7)
return true;
}
+ break;
case ArchSpec::kCore_hexagon_any:
if ((core2 >= ArchSpec::kCore_hexagon_first && core2 <= ArchSpec::kCore_hexagon_last) || (core2 == ArchSpec::kCore_hexagon_any))
@@ -937,9 +1019,63 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
case ArchSpec::eCore_arm_armv7s:
if (!enforce_exact_match)
{
- try_inverse = false;
+ if (core2 == ArchSpec::eCore_arm_generic)
+ return true;
if (core2 == ArchSpec::eCore_arm_armv7)
return true;
+ try_inverse = false;
+ }
+ break;
+
+ case ArchSpec::eCore_x86_64_x86_64h:
+ if (!enforce_exact_match)
+ {
+ try_inverse = false;
+ if (core2 == ArchSpec::eCore_x86_64_x86_64)
+ return true;
+ }
+ 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)
+ {
+ if (core2 == ArchSpec::eCore_arm_arm64)
+ return true;
+ if (core2 == ArchSpec::eCore_arm_aarch64)
+ return true;
+ try_inverse = false;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_aarch64:
+ if (!enforce_exact_match)
+ {
+ if (core2 == ArchSpec::eCore_arm_arm64)
+ return true;
+ if (core2 == ArchSpec::eCore_arm_armv8)
+ return true;
+ try_inverse = false;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_arm64:
+ if (!enforce_exact_match)
+ {
+ if (core2 == ArchSpec::eCore_arm_aarch64)
+ return true;
+ if (core2 == ArchSpec::eCore_arm_armv8)
+ return true;
+ try_inverse = false;
}
break;
diff --git a/source/Core/Broadcaster.cpp b/source/Core/Broadcaster.cpp
index 88f39961832f..dc37516c29c2 100644
--- a/source/Core/Broadcaster.cpp
+++ b/source/Core/Broadcaster.cpp
@@ -31,15 +31,16 @@ Broadcaster::Broadcaster (BroadcasterManager *manager, const char *name) :
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p Broadcaster::Broadcaster(\"%s\")", this, m_broadcaster_name.AsCString());
-
+ log->Printf ("%p Broadcaster::Broadcaster(\"%s\")",
+ static_cast<void*>(this), m_broadcaster_name.AsCString());
}
Broadcaster::~Broadcaster()
{
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p Broadcaster::~Broadcaster(\"%s\")", this, m_broadcaster_name.AsCString());
+ log->Printf ("%p Broadcaster::~Broadcaster(\"%s\")",
+ static_cast<void*>(this), m_broadcaster_name.AsCString());
Clear();
}
@@ -226,7 +227,7 @@ Broadcaster::PrivateBroadcastEvent (EventSP &event_sp, bool unique)
const uint32_t event_type = event_sp->GetType();
Mutex::Locker event_types_locker(m_listeners_mutex);
-
+
Listener *hijacking_listener = NULL;
if (!m_hijacking_listeners.empty())
{
@@ -242,11 +243,9 @@ Broadcaster::PrivateBroadcastEvent (EventSP &event_sp, bool unique)
StreamString event_description;
event_sp->Dump (&event_description);
log->Printf ("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, unique =%i) hijack = %p",
- this,
- m_broadcaster_name.AsCString(""),
- event_description.GetData(),
- unique,
- hijacking_listener);
+ static_cast<void*>(this), m_broadcaster_name.AsCString(""),
+ event_description.GetData(), unique,
+ static_cast<void*>(hijacking_listener));
}
if (hijacking_listener)
@@ -293,16 +292,12 @@ bool
Broadcaster::HijackBroadcaster (Listener *listener, uint32_t event_mask)
{
Mutex::Locker event_types_locker(m_listeners_mutex);
-
+
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
if (log)
- {
log->Printf ("%p Broadcaster(\"%s\")::HijackBroadcaster (listener(\"%s\")=%p)",
- this,
- m_broadcaster_name.AsCString(""),
- listener->m_name.c_str(),
- listener);
- }
+ static_cast<void*>(this), m_broadcaster_name.AsCString(""),
+ listener->m_name.c_str(), static_cast<void*>(listener));
m_hijacking_listeners.push_back(listener);
m_hijacking_masks.push_back(event_mask);
return true;
@@ -320,10 +315,9 @@ Broadcaster::RestoreBroadcaster ()
{
Listener *listener = m_hijacking_listeners.back();
log->Printf ("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop listener(\"%s\")=%p)",
- this,
+ static_cast<void*>(this),
m_broadcaster_name.AsCString(""),
- listener->m_name.c_str(),
- listener);
+ listener->m_name.c_str(), static_cast<void*>(listener));
}
m_hijacking_listeners.pop_back();
}
diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp
index f05ce320b5be..d71c9881a6f3 100644
--- a/source/Core/Communication.cpp
+++ b/source/Core/Communication.cpp
@@ -380,11 +380,24 @@ Communication::ReadThread (lldb::thread_arg_t p)
if (comm->GetCloseOnEOF())
done = true;
break;
+ case eConnectionStatusError: // Check GetError() for details
+ if (error.GetType() == eErrorTypePOSIX && error.GetError() == EIO)
+ {
+ // EIO on a pipe is usually caused by remote shutdown
+ comm->Disconnect ();
+ done = true;
+ }
+ if (log)
+ error.LogIfError (log,
+ "%p Communication::ReadFromConnection () => status = %s",
+ p,
+ Communication::ConnectionStatusAsCString (status));
+ break;
case eConnectionStatusNoConnection: // No connection
case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection
+ case eConnectionStatusInterrupted: // Interrupted
done = true;
// Fall through...
- case eConnectionStatusError: // Check GetError() for details
case eConnectionStatusTimedOut: // Request timed out
if (log)
error.LogIfError (log,
@@ -433,6 +446,7 @@ Communication::ConnectionStatusAsCString (lldb::ConnectionStatus status)
case eConnectionStatusNoConnection: return "no connection";
case eConnectionStatusLostConnection: return "lost connection";
case eConnectionStatusEndOfFile: return "end of file";
+ case eConnectionStatusInterrupted: return "interrupted";
}
static char unknown_state_string[64];
diff --git a/source/Core/ConnectionFileDescriptor.cpp b/source/Core/ConnectionFileDescriptor.cpp
index ed876e52c9af..7c8e98a21129 100644
--- a/source/Core/ConnectionFileDescriptor.cpp
+++ b/source/Core/ConnectionFileDescriptor.cpp
@@ -16,7 +16,9 @@
#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 <errno.h>
@@ -24,20 +26,9 @@
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
+
#ifndef LLDB_DISABLE_POSIX
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/socket.h>
-#include <sys/un.h>
#include <termios.h>
-#include <unistd.h>
-#endif
-#ifdef _WIN32
-#include "lldb/Host/windows/windows.h"
-#include <winsock2.h>
-#include <WS2tcpip.h>
#endif
// C++ Includes
@@ -48,84 +39,44 @@
#endif
// Project includes
#include "lldb/lldb-private-log.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/Log.h"
-#include "lldb/Core/RegularExpression.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;
-static bool
-DecodeHostAndPort (const char *host_and_port,
- std::string &host_str,
- std::string &port_str,
- int32_t& port,
- Error *error_ptr)
-{
- static RegularExpression g_regex ("([^:]+):([0-9]+)");
- RegularExpression::Match regex_match(2);
- if (g_regex.Execute (host_and_port, &regex_match))
- {
- if (regex_match.GetMatchAtIndex (host_and_port, 1, host_str) &&
- regex_match.GetMatchAtIndex (host_and_port, 2, port_str))
- {
- port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN);
- if (port != INT32_MIN)
- {
- if (error_ptr)
- error_ptr->Clear();
- return true;
- }
- }
- }
- host_str.clear();
- port_str.clear();
- port = INT32_MIN;
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port);
- return false;
-}
-
ConnectionFileDescriptor::ConnectionFileDescriptor () :
Connection(),
- m_fd_send (-1),
- m_fd_recv (-1),
- m_fd_send_type (eFDTypeFile),
- m_fd_recv_type (eFDTypeFile),
- m_udp_send_sockaddr (new SocketAddress()),
- m_socket_timeout_usec(0),
- m_pipe_read(-1),
- m_pipe_write(-1),
+ m_pipe (),
m_mutex (Mutex::eMutexTypeRecursive),
- m_should_close_fd (false),
- m_shutting_down (false)
+ 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 ()", this);
+ log->Printf ("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()",
+ static_cast<void*>(this));
}
ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) :
Connection(),
- m_fd_send (fd),
- m_fd_recv (fd),
- m_fd_send_type (eFDTypeFile),
- m_fd_recv_type (eFDTypeFile),
- m_udp_send_sockaddr (new SocketAddress()),
- m_socket_timeout_usec(0),
- m_pipe_read(-1),
- m_pipe_write(-1),
+ m_pipe (),
m_mutex (Mutex::eMutexTypeRecursive),
- m_should_close_fd (owns_fd),
- m_shutting_down (false)
+ 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)", this, fd, owns_fd);
+ log->Printf ("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)",
+ static_cast<void*>(this), fd, owns_fd);
OpenCommandPipe ();
}
@@ -134,7 +85,8 @@ ConnectionFileDescriptor::~ConnectionFileDescriptor ()
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", this);
+ log->Printf ("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()",
+ static_cast<void*>(this));
Disconnect (NULL);
CloseCommandPipe ();
}
@@ -143,31 +95,22 @@ void
ConnectionFileDescriptor::OpenCommandPipe ()
{
CloseCommandPipe();
-
+
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
// Make the command file descriptor here:
- int filedes[2];
-#ifndef LLDB_DISABLE_POSIX
- int result = pipe (filedes);
-#else
- int result = -1;
-#endif
- if (result != 0)
+ if (!m_pipe.Open())
{
if (log)
log->Printf ("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s",
- this,
- strerror(errno));
+ static_cast<void*>(this), strerror(errno));
}
else
{
- m_pipe_read = filedes[0];
- m_pipe_write = filedes[1];
if (log)
log->Printf ("%p ConnectionFileDescriptor::OpenCommandPipe() - success readfd=%d writefd=%d",
- this,
- m_pipe_read,
- m_pipe_write);
+ static_cast<void*>(this),
+ m_pipe.GetReadFileDescriptor(),
+ m_pipe.GetWriteFileDescriptor());
}
}
@@ -177,33 +120,15 @@ ConnectionFileDescriptor::CloseCommandPipe ()
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
if (log)
log->Printf ("%p ConnectionFileDescriptor::CloseCommandPipe()",
- this);
+ static_cast<void*>(this));
- if (m_pipe_read != -1)
- {
-#ifdef _MSC_VER
- llvm_unreachable("pipe close unsupported in MSVC");
-#else
- close (m_pipe_read);
-#endif
- m_pipe_read = -1;
- }
-
- if (m_pipe_write != -1)
- {
-#ifdef _MSC_VER
- llvm_unreachable("pipe close unsupported in MSVC");
-#else
- close (m_pipe_write);
-#endif
- m_pipe_write = -1;
- }
+ m_pipe.Close();
}
bool
ConnectionFileDescriptor::IsConnected () const
{
- return m_fd_send >= 0 || m_fd_recv >= 0;
+ return (m_read_sp && m_read_sp->IsValid()) || (m_write_sp && m_write_sp->IsValid());
}
ConnectionStatus
@@ -212,47 +137,52 @@ 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')", this, s);
+ log->Printf ("%p ConnectionFileDescriptor::Connect (url = '%s')",
+ static_cast<void*>(this), s);
OpenCommandPipe();
-
+
if (s && s[0])
{
- if (strstr(s, "listen://"))
+ if (strstr(s, "listen://") == s)
{
// listen://HOST:PORT
return SocketListen (s + strlen("listen://"), error_ptr);
}
- else if (strstr(s, "accept://"))
+ else if (strstr(s, "accept://") == s)
{
// unix://SOCKNAME
return NamedSocketAccept (s + strlen("accept://"), error_ptr);
}
- else if (strstr(s, "unix-accept://"))
+ else if (strstr(s, "unix-accept://") == s)
{
// unix://SOCKNAME
return NamedSocketAccept (s + strlen("unix-accept://"), error_ptr);
}
- else if (strstr(s, "connect://"))
+ else if (strstr(s, "connect://") == s)
{
return ConnectTCP (s + strlen("connect://"), error_ptr);
}
- else if (strstr(s, "tcp-connect://"))
+ else if (strstr(s, "tcp-connect://") == s)
{
return ConnectTCP (s + strlen("tcp-connect://"), error_ptr);
}
- else if (strstr(s, "udp://"))
+ else if (strstr(s, "udp://") == s)
{
return ConnectUDP (s + strlen("udp://"), error_ptr);
}
- else if (strstr(s, "fd://"))
+#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;
- m_fd_send = m_fd_recv = Args::StringToSInt32 (s, -1, 0, &success);
-
+ int fd = Args::StringToSInt32 (s, -1, 0, &success);
+
if (success)
{
// We have what looks to be a valid file descriptor, but we
@@ -260,26 +190,17 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
// get the flags from the file descriptor and making sure it
// isn't a bad fd.
errno = 0;
-#ifndef LLDB_DISABLE_POSIX
- int flags = ::fcntl (m_fd_send, F_GETFL, 0);
-#else
- int flags = -1;
-#endif
+ int flags = ::fcntl (fd, F_GETFL, 0);
if (flags == -1 || errno == EBADF)
{
if (error_ptr)
error_ptr->SetErrorStringWithFormat ("stale file descriptor: %s", s);
- m_fd_send = m_fd_recv = -1;
+ m_read_sp.reset();
+ m_write_sp.reset();
return eConnectionStatusError;
}
else
{
- // 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 = GetSocketOption (m_fd_send, SOL_SOCKET, SO_REUSEADDR, resuse) == 0;
- if (is_socket)
- m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
// 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.
@@ -289,37 +210,55 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
// 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.
- m_should_close_fd = false;
+
+ std::unique_ptr<Socket> 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_fd_send = m_fd_recv = -1;
+ m_read_sp.reset();
+ m_write_sp.reset();
return eConnectionStatusError;
}
- else if (strstr(s, "file://"))
+ else if (strstr(s, "file://") == s)
{
// file:///PATH
const char *path = s + strlen("file://");
-#ifndef LLDB_DISABLE_POSIX
+ int fd = -1;
do
{
- m_fd_send = m_fd_recv = ::open (path, O_RDWR);
- } while (m_fd_send == -1 && errno == EINTR);
- if (m_fd_send == -1)
+ fd = ::open (path, O_RDWR);
+ } while (fd == -1 && errno == EINTR);
+
+ if (fd == -1)
{
if (error_ptr)
error_ptr->SetErrorToErrno();
return eConnectionStatusError;
}
- if (::isatty(m_fd_send))
+ if (::isatty(fd))
{
// Set up serial terminal emulation
struct termios options;
- ::tcgetattr (m_fd_send, &options);
+ ::tcgetattr (fd, &options);
// Set port speed to maximum
::cfsetospeed (&options, B115200);
@@ -332,24 +271,23 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 0;
- ::tcsetattr (m_fd_send, TCSANOW, &options);
+ ::tcsetattr (fd, TCSANOW, &options);
}
- int flags = ::fcntl (m_fd_send, F_GETFL, 0);
+ int flags = ::fcntl (fd, F_GETFL, 0);
if (flags >= 0)
{
if ((flags & O_NONBLOCK) == 0)
{
flags |= O_NONBLOCK;
- ::fcntl (m_fd_send, F_SETFL, flags);
+ ::fcntl (fd, F_SETFL, flags);
}
}
- m_should_close_fd = true;
+ m_read_sp.reset(new File(fd, true));
+ m_write_sp.reset(new File(fd, false));
return eConnectionStatusSuccess;
-#else
- return eConnectionStatusError;
-#endif
}
+#endif
if (error_ptr)
error_ptr->SetErrorStringWithFormat ("unsupported connection URL: '%s'", s);
return eConnectionStatusError;
@@ -359,81 +297,70 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
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 ()", this);
-
- // Reset the port predicate when disconnecting and don't broadcast
- m_port_predicate.SetValue(0, eBroadcastNever);
+ log->Printf ("%p ConnectionFileDescriptor::Disconnect ()",
+ static_cast<void*>(this));
ConnectionStatus status = eConnectionStatusSuccess;
- if (m_fd_send < 0 && m_fd_recv < 0)
+ if (!IsConnected())
{
if (log)
- log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", this);
+ log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect",
+ static_cast<void*>(this));
return eConnectionStatusSuccess;
}
-
+
+ if (m_read_sp && m_read_sp->IsValid() && m_read_sp->GetFdType() == IOObject::eFDTypeSocket)
+ static_cast<Socket&>(*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);
-
+ bool got_lock = locker.TryLock (m_mutex);
+
if (!got_lock)
{
- if (m_pipe_write != -1 )
+ if (m_pipe.WriteDescriptorIsValid())
{
int result;
- result = write (m_pipe_write, "q", 1);
+ 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.", this, m_pipe_write, result);
+ log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, sent 'q' to %d, result = %d.",
+ static_cast<void*>(this), m_pipe.GetWriteFileDescriptor(), result);
}
else if (log)
- log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.", this);
- locker.Lock (m_mutex);
- }
-
- if (m_should_close_fd == true)
- {
- if (m_fd_send == m_fd_recv)
- {
- status = Close (m_fd_send, m_fd_send_type, error_ptr);
- }
- else
{
- // File descriptors are the different, close both if needed
- if (m_fd_send >= 0)
- status = Close (m_fd_send, m_fd_send_type, error_ptr);
- if (m_fd_recv >= 0)
- {
- ConnectionStatus recv_status = Close (m_fd_recv, m_fd_recv_type, error_ptr);
- if (status == eConnectionStatusSuccess)
- status = recv_status;
- }
+ log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.",
+ static_cast<void*>(this));
}
+ locker.Lock (m_mutex);
}
- // Now set all our descriptors to invalid values.
-
- m_fd_send = m_fd_recv = -1;
+ 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;
- if (status != eConnectionStatusSuccess)
- {
-
- return status;
- }
-
m_shutting_down = false;
- return eConnectionStatusSuccess;
+ return status;
}
size_t
@@ -444,9 +371,6 @@ ConnectionFileDescriptor::Read (void *dst,
Error *error_ptr)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %" PRIu64 ")...",
- this, m_fd_recv, dst, (uint64_t)dst_len);
Mutex::Locker locker;
bool got_lock = locker.TryLock (m_mutex);
@@ -454,67 +378,40 @@ ConnectionFileDescriptor::Read (void *dst,
{
if (log)
log->Printf ("%p ConnectionFileDescriptor::Read () failed to get the connection lock.",
- this);
+ static_cast<void*>(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;
-
- ssize_t bytes_read = 0;
status = BytesAvailable (timeout_usec, error_ptr);
- if (status == eConnectionStatusSuccess)
- {
- do
- {
-#ifndef LLDB_DISABLE_POSIX
- bytes_read = ::read (m_fd_recv, dst, dst_len);
-#else
- switch (m_fd_send_type) {
- case eFDTypeSocket:
- case eFDTypeSocketUDP:
- bytes_read = ::recv (m_fd_recv, (char*)dst, dst_len, 0);
- break;
- default:
- bytes_read = -1;
- break;
-
- }
-
-#endif
- } while (bytes_read < 0 && errno == EINTR);
- }
-
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<void*>(this),
+ static_cast<uint64_t>(m_read_sp->GetWaitableHandle()),
+ static_cast<void*>(dst),
+ static_cast<uint64_t>(dst_len),
+ static_cast<uint64_t>(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;
}
- else if (bytes_read < 0)
- {
- error.SetErrorToErrno();
- }
- else
- {
- error.Clear();
- }
-
- if (log)
- log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %" PRIu64 ") => %" PRIi64 ", error = %s",
- this,
- m_fd_recv,
- dst,
- (uint64_t)dst_len,
- (int64_t)bytes_read,
- error.AsCString());
if (error_ptr)
*error_ptr = error;
@@ -525,7 +422,7 @@ ConnectionFileDescriptor::Read (void *dst,
switch (error_value)
{
case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read.
- if (m_fd_recv_type == eFDTypeSocket || m_fd_recv_type == eFDTypeSocketUDP)
+ if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket)
status = eConnectionStatusTimedOut;
else
status = eConnectionStatusSuccess;
@@ -562,7 +459,8 @@ ConnectionFileDescriptor::Read (void *dst,
default:
if (log)
- log->Printf("%p ConnectionFileDescriptor::Read (), unexpected error: %s", this, strerror(error_value));
+ log->Printf("%p ConnectionFileDescriptor::Read (), unexpected error: %s",
+ static_cast<void*>(this), strerror(error_value));
status = eConnectionStatusError;
break; // Break to close....
@@ -578,7 +476,9 @@ ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStat
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
if (log)
- log->Printf ("%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")", this, src, (uint64_t)src_len);
+ log->Printf ("%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")",
+ static_cast<void*>(this), static_cast<const void*>(src),
+ static_cast<uint64_t>(src_len));
if (!IsConnected ())
{
@@ -591,78 +491,18 @@ ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStat
Error error;
- ssize_t bytes_sent = 0;
-
- switch (m_fd_send_type)
- {
-#ifndef LLDB_DISABLE_POSIX
- case eFDTypeFile: // Other FD requireing read/write
- do
- {
- bytes_sent = ::write (m_fd_send, src, src_len);
- } while (bytes_sent < 0 && errno == EINTR);
- break;
-#endif
- case eFDTypeSocket: // Socket requiring send/recv
- do
- {
- bytes_sent = ::send (m_fd_send, (char*)src, src_len, 0);
- } while (bytes_sent < 0 && errno == EINTR);
- break;
-
- case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom
- assert (m_udp_send_sockaddr->GetFamily() != 0);
- do
- {
- bytes_sent = ::sendto (m_fd_send,
- (char*)src,
- src_len,
- 0,
- *m_udp_send_sockaddr,
- m_udp_send_sockaddr->GetLength());
- } while (bytes_sent < 0 && errno == EINTR);
- break;
- }
-
- if (bytes_sent < 0)
- error.SetErrorToErrno ();
- else
- error.Clear ();
+ size_t bytes_sent = src_len;
+ error = m_write_sp->Write(src, bytes_sent);
if (log)
{
- switch (m_fd_send_type)
- {
- case eFDTypeFile: // Other FD requireing read/write
- log->Printf ("%p ConnectionFileDescriptor::Write() ::write (fd = %i, src = %p, src_len = %" PRIu64 ") => %" PRIi64 " (error = %s)",
- this,
- m_fd_send,
- src,
- (uint64_t)src_len,
- (int64_t)bytes_sent,
- error.AsCString());
- break;
-
- case eFDTypeSocket: // Socket requiring send/recv
- log->Printf ("%p ConnectionFileDescriptor::Write() ::send (socket = %i, src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
- this,
- m_fd_send,
- src,
- (uint64_t)src_len,
- (int64_t)bytes_sent,
- error.AsCString());
- break;
-
- case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom
- log->Printf ("%p ConnectionFileDescriptor::Write() ::sendto (socket = %i, src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
- this,
- m_fd_send,
- src,
- (uint64_t)src_len,
- (int64_t)bytes_sent,
- error.AsCString());
- break;
- }
+ log->Printf ("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)",
+ static_cast<void*>(this),
+ static_cast<uint64_t>(m_write_sp->GetWaitableHandle()),
+ static_cast<const void*>(src),
+ static_cast<uint64_t>(src_len),
+ static_cast<uint64_t>(bytes_sent),
+ error.AsCString());
}
if (error_ptr)
@@ -696,34 +536,43 @@ ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStat
-#if defined(__APPLE__)
-
// This ConnectionFileDescriptor::BytesAvailable() uses select().
//
// PROS:
// - select is consistent across most unix platforms
-// - this Apple specific version allows for unlimited fds in the fd_sets by
+// - 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:
-// - Darwin only
+// - 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::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_CONNECTION));
if (log)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", this, timeout_usec);
+ log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)",
+ static_cast<void*>(this), timeout_usec);
+
struct timeval *tv_ptr;
struct timeval tv;
if (timeout_usec == UINT32_MAX)
{
- // Infinite wait...
- tv_ptr = NULL;
+ // Inifinite wait...
+ tv_ptr = nullptr;
}
else
{
@@ -733,20 +582,32 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt
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 int data_fd = m_fd_recv;
- const int pipe_fd = m_pipe_read;
-
- if (data_fd >= 0)
+ 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;
-
- while (data_fd == m_fd_recv)
+#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<int>(data_fd, pipe_fd) + 1;
+ const int nfds = std::max<int>(handle, pipe_fd) + 1;
+#if defined(__APPLE__)
llvm::SmallVector<fd_set, 1> read_fds;
read_fds.resize((nfds/FD_SETSIZE) + 1);
for (size_t i=0; i<read_fds.size(); ++i)
@@ -754,360 +615,62 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt
// 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
- FD_SET (data_fd, read_fds.data());
- if (have_pipe_fd)
- FD_SET (pipe_fd, read_fds.data());
-
- Error error;
-
- if (log)
- {
- if (have_pipe_fd)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p)...",
- this, nfds, data_fd, pipe_fd, tv_ptr);
- else
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p)...",
- this, nfds, data_fd, tv_ptr);
- }
-
- const int num_set_fds = ::select (nfds, read_fds.data(), 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",
- this, nfds, data_fd, pipe_fd, 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",
- this, nfds, data_fd, 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)
- {
- // FD_ISSET is happy to deal with a something larger than
- // a single fd_set.
- if (FD_ISSET(data_fd, read_fds.data()))
- return eConnectionStatusSuccess;
- if (have_pipe_fd && FD_ISSET(pipe_fd, read_fds.data()))
- {
- // 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);
- assert (bytes_read == 1 && buffer[0] == 'q');
-
- if (log)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.",
- this, (int) bytes_read, buffer);
-
- return eConnectionStatusEndOfFile;
- }
- }
- }
- }
-
- if (error_ptr)
- error_ptr->SetErrorString("not connected");
- return eConnectionStatusLostConnection;
-}
-
#else
-
-// This ConnectionFileDescriptor::BytesAvailable() uses select().
-//
-// PROS:
-// - select is consistent across most unix platforms
-// CONS:
-// - 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. MacOSX
-// uses kqueues, and there is a poll() based implementation below.
-
-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::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", this, timeout_usec);
- struct timeval *tv_ptr;
- struct timeval tv;
- if (timeout_usec == UINT32_MAX)
- {
- // Infinite wait...
- tv_ptr = NULL;
- }
- 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 int data_fd = m_fd_recv;
- const int pipe_fd = m_pipe_read;
-
- if (data_fd >= 0)
- {
- // If this assert fires off on MacOSX, we will need to switch to using
- // libdispatch to read from file descriptors because poll() is causing
- // kernel panics and if we exceed FD_SETSIZE we will have no choice...
-#ifndef _MSC_VER
- assert (data_fd < FD_SETSIZE);
-#endif
-
- const bool have_pipe_fd = pipe_fd >= 0;
-
- if (have_pipe_fd)
- {
- assert (pipe_fd < FD_SETSIZE);
- }
-
- while (data_fd == m_fd_recv)
- {
fd_set read_fds;
FD_ZERO (&read_fds);
- FD_SET (data_fd, &read_fds);
+#endif
+ FD_SET (handle, FD_SET_DATA(read_fds));
if (have_pipe_fd)
- FD_SET (pipe_fd, &read_fds);
-
- const int nfds = std::max<int>(data_fd, pipe_fd) + 1;
+ 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)...",
- this, nfds, data_fd, pipe_fd, tv_ptr);
+ static_cast<void*>(this), nfds, handle, pipe_fd,
+ static_cast<void*>(tv_ptr));
else
log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p)...",
- this, nfds, data_fd, tv_ptr);
+ static_cast<void*>(this), nfds, handle,
+ static_cast<void*>(tv_ptr));
}
-
- const int num_set_fds = ::select (nfds, &read_fds, NULL, NULL, 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",
- this, nfds, data_fd, pipe_fd, tv_ptr, num_set_fds, error.AsCString());
+ static_cast<void*>(this), nfds, handle,
+ pipe_fd, static_cast<void*>(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",
- this, nfds, data_fd, tv_ptr, num_set_fds, error.AsCString());
+ static_cast<void*>(this), nfds, handle,
+ static_cast<void*>(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(data_fd, &read_fds))
- return eConnectionStatusSuccess;
- if (have_pipe_fd && FD_ISSET(pipe_fd, &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);
- assert (bytes_read == 1 && buffer[0] == 'q');
-
- if (log)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.",
- this, (int) bytes_read, buffer);
-
- return eConnectionStatusEndOfFile;
- }
- }
- }
- }
-
- if (error_ptr)
- error_ptr->SetErrorString("not connected");
- return eConnectionStatusLostConnection;
-}
-
-#endif
-#if 0
-#include <poll.h>
-
-// This ConnectionFileDescriptor::BytesAvailable() uses poll(). poll() should NOT
-// be used on MacOSX as it has all sorts of restrictions on the types of file descriptors
-// that it doesn't support.
-//
-// There may be some systems that properly support poll() that could use this
-// implementation. I will let each system opt into this on their own.
-//
-// PROS:
-// - no restrictions on the fd value that is used
-// CONS:
-// - varies wildly from platform to platform in its implementation restrictions
-
-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::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", this, timeout_usec);
- int timeout_msec = 0;
- if (timeout_usec == UINT32_MAX)
- {
- // Infinite wait...
- timeout_msec = -1;
- }
- else if (timeout_usec == 0)
- {
- // Return immediately, don't wait
- timeout_msec = 0;
- }
- else
- {
- // Convert usec to msec
- timeout_msec = (timeout_usec + 999) / 1000;
- }
-
- // 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 int data_fd = m_fd_recv;
- const int pipe_fd = m_pipe_read;
-
- // Make sure the file descriptor can be used with select as it
- // must be in range
- if (data_fd >= 0)
- {
- const bool have_pipe_fd = pipe_fd >= 0;
- struct pollfd fds[2] =
- {
- { data_fd, POLLIN, 0 },
- { pipe_fd, POLLIN, 0 }
- };
- const int nfds = have_pipe_fd ? 2 : 1;
- Error error;
- while (data_fd == m_fd_recv)
- {
- const int num_set_fds = ::poll (fds, nfds, timeout_msec);
-
- if (num_set_fds < 0)
- error.SetErrorToErrno();
- else
- error.Clear();
-
- if (error_ptr)
- *error_ptr = error;
-
- if (log)
- {
- if (have_pipe_fd)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::poll (fds={{%i,POLLIN},{%i,POLLIN}}, nfds=%i, timeout_ms=%i) => %d, error = %s\n",
- this,
- data_fd,
- pipe_fd,
- nfds,
- timeout_msec,
- num_set_fds,
- error.AsCString());
- else
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::poll (fds={{%i,POLLIN}}, nfds=%i, timeout_ms=%i) => %d, error = %s\n",
- this,
- data_fd,
- nfds,
- timeout_msec,
- num_set_fds,
- error.AsCString());
- }
-
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
@@ -1123,595 +686,121 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt
}
else if (num_set_fds > 0)
{
- if (fds[0].revents & POLLIN)
+ if (FD_ISSET(handle, FD_SET_DATA(read_fds)))
return eConnectionStatusSuccess;
- if (fds[1].revents & POLLIN)
+ 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);
- assert (bytes_read == 1 && buffer[0] == 'q');
- if (log)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.",
- this, (int) bytes_read, buffer);
-
- return eConnectionStatusEndOfFile;
+ switch (buffer[0])
+ {
+ case 'q':
+ if (log)
+ log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.",
+ static_cast<void*>(this),
+ static_cast<int>(bytes_read), buffer);
+ return eConnectionStatusEndOfFile;
+ case 'i':
+ // Interrupt the current read
+ return eConnectionStatusInterrupted;
+ }
}
}
}
}
+
if (error_ptr)
error_ptr->SetErrorString("not connected");
return eConnectionStatusLostConnection;
}
-#endif
-
-ConnectionStatus
-ConnectionFileDescriptor::Close (int& fd, FDType type, Error *error_ptr)
-{
- if (error_ptr)
- error_ptr->Clear();
- bool success = true;
- // Avoid taking a lock if we can
- if (fd >= 0)
- {
- Mutex::Locker locker (m_mutex);
- // Check the FD after the lock is taken to ensure only one thread
- // can get into the close scope below
- if (fd >= 0)
- {
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf ("%p ConnectionFileDescriptor::Close (fd = %i)", this,fd);
-#if _WIN32
- if (type != eFDTypeFile)
- success = closesocket(fd) == 0;
- else
-#endif
- success = ::close (fd) == 0;
- // A reference to a FD was passed in, set it to an invalid value
- fd = -1;
- if (!success && error_ptr)
- {
- // Only set the error if we have been asked to since something else
- // might have caused us to try and shut down the connection and may
- // have already set the error.
- error_ptr->SetErrorToErrno();
- }
- }
- }
- if (success)
- return eConnectionStatusSuccess;
- else
- return eConnectionStatusError;
-}
-
ConnectionStatus
ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *error_ptr)
{
-#ifndef LLDB_DISABLE_POSIX
- ConnectionStatus result = eConnectionStatusError;
- struct sockaddr_un saddr_un;
-
- m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
-
- int listen_socket = ::socket (AF_UNIX, SOCK_STREAM, 0);
- if (listen_socket == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- return eConnectionStatusError;
- }
-
- saddr_un.sun_family = AF_UNIX;
- ::strncpy(saddr_un.sun_path, socket_name, sizeof(saddr_un.sun_path) - 1);
- saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
- saddr_un.sun_len = SUN_LEN (&saddr_un);
-#endif
-
- Host::Unlink (socket_name);
- if (::bind (listen_socket, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0)
- {
- if (::listen (listen_socket, 5) == 0)
- {
- m_fd_send = m_fd_recv = ::accept (listen_socket, NULL, 0);
- if (m_fd_send > 0)
- {
- m_should_close_fd = true;
-
- if (error_ptr)
- error_ptr->Clear();
- result = eConnectionStatusSuccess;
- }
- }
- }
-
- if (result != eConnectionStatusSuccess)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- }
- // We are done with the listen port
- Close (listen_socket, eFDTypeSocket, NULL);
- return result;
-#else
- return eConnectionStatusError;
-#endif
+ 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)
{
-#ifndef LLDB_DISABLE_POSIX
- Disconnect (NULL);
- m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
-
- // Open the socket that was passed in as an option
- struct sockaddr_un saddr_un;
- m_fd_send = m_fd_recv = ::socket (AF_UNIX, SOCK_STREAM, 0);
- if (m_fd_send == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- return eConnectionStatusError;
- }
-
- saddr_un.sun_family = AF_UNIX;
- ::strncpy(saddr_un.sun_path, socket_name, sizeof(saddr_un.sun_path) - 1);
- saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
- saddr_un.sun_len = SUN_LEN (&saddr_un);
-#endif
-
- if (::connect (m_fd_send, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- Disconnect (NULL);
- return eConnectionStatusError;
- }
+ Socket* socket = nullptr;
+ Error error = Socket::UnixDomainConnect(socket_name, socket);
if (error_ptr)
- error_ptr->Clear();
- return eConnectionStatusSuccess;
-#else
- return eConnectionStatusError;
-#endif
+ *error_ptr = error;
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError;
}
ConnectionStatus
-ConnectionFileDescriptor::SocketListen (const char *host_and_port, Error *error_ptr)
+ConnectionFileDescriptor::SocketListen(const char *s, Error *error_ptr)
{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf ("%p ConnectionFileDescriptor::SocketListen (%s)", this, host_and_port);
-
- Disconnect (NULL);
- m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
- std::string host_str;
- std::string port_str;
- int32_t port = INT32_MIN;
- if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, error_ptr))
- {
- // Might be just a port number
- port = Args::StringToSInt32(host_and_port, -1);
- if (port == -1)
- return eConnectionStatusError;
- else
- host_str.clear();
- }
- const sa_family_t family = AF_INET;
- const int socktype = SOCK_STREAM;
- const int protocol = IPPROTO_TCP;
- int listen_fd = ::socket (family, socktype, protocol);
- if (listen_fd == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- return eConnectionStatusError;
- }
-
- // enable local address reuse
- SetSocketOption (listen_fd, SOL_SOCKET, SO_REUSEADDR, 1);
-
- SocketAddress listen_addr;
- if (host_str.empty())
- listen_addr.SetToLocalhost(family, port);
- else if (host_str.compare("*") == 0)
- listen_addr.SetToAnyAddress(family, port);
- else
- {
- if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol))
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str());
- Close (listen_fd, eFDTypeSocket, NULL);
- return eConnectionStatusError;
- }
- }
-
- SocketAddress anyaddr;
- if (anyaddr.SetToAnyAddress (family, port))
- {
- int err = ::bind (listen_fd, anyaddr, anyaddr.GetLength());
- if (err == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- Close (listen_fd, eFDTypeSocket, NULL);
- return eConnectionStatusError;
- }
-
- err = ::listen (listen_fd, 1);
- if (err == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- Close (listen_fd, eFDTypeSocket, NULL);
- return eConnectionStatusError;
- }
-
- // We were asked to listen on port zero which means we
- // must now read the actual port that was given to us
- // as port zero is a special code for "find an open port
- // for me".
- if (port == 0)
- port = GetSocketPort(listen_fd);
-
- // Set the port predicate since when doing a listen://<host>:<port>
- // it often needs to accept the incoming connection which is a blocking
- // system call. Allowing access to the bound port using a predicate allows
- // us to wait for the port predicate to be set to a non-zero value from
- // another thread in an efficient manor.
- m_port_predicate.SetValue(port, eBroadcastAlways);
-
-
- bool accept_connection = false;
-
- // Loop until we are happy with our connection
- while (!accept_connection)
- {
- struct sockaddr_in accept_addr;
- ::memset (&accept_addr, 0, sizeof accept_addr);
-#if !(defined (__linux__) || defined(_MSC_VER))
- accept_addr.sin_len = sizeof accept_addr;
-#endif
- socklen_t accept_addr_len = sizeof accept_addr;
-
- int fd = ::accept (listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len);
-
- if (fd == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- break;
- }
-
- if (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)
- {
- accept_connection = true;
- m_fd_send = m_fd_recv = fd;
- }
- else
- {
- if (
-#if !(defined(__linux__) || (defined(_MSC_VER)))
- accept_addr_len == listen_addr.sockaddr_in().sin_len &&
-#endif
- accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr)
- {
- accept_connection = true;
- m_fd_send = m_fd_recv = fd;
- }
- else
- {
- ::close (fd);
- m_fd_send = m_fd_recv = -1;
- const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
- const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
- ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n",
- accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
- listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
- }
- }
- }
-
- if (m_fd_send == -1)
- {
- Close (listen_fd, eFDTypeSocket, NULL);
- return eConnectionStatusError;
- }
- }
-
- // We are done with the listen port
- Close (listen_fd, eFDTypeSocket, NULL);
-
- m_should_close_fd = true;
+ m_port_predicate.SetValue(0, eBroadcastNever);
- // Keep our TCP packets coming without any delays.
- SetSocketOption (m_fd_send, IPPROTO_TCP, TCP_NODELAY, 1);
+ Socket* socket = nullptr;
+ m_waiting_for_accept = true;
+ Error error = Socket::TcpListen(s, socket, &m_port_predicate);
if (error_ptr)
- error_ptr->Clear();
- return eConnectionStatusSuccess;
-}
-
-ConnectionStatus
-ConnectionFileDescriptor::ConnectTCP (const char *host_and_port, Error *error_ptr)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf ("%p ConnectionFileDescriptor::ConnectTCP (host/port = %s)", this, host_and_port);
- Disconnect (NULL);
-
- m_fd_send_type = m_fd_recv_type = eFDTypeSocket;
- std::string host_str;
- std::string port_str;
- int32_t port = INT32_MIN;
- if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, error_ptr))
- return eConnectionStatusError;
-
- // Create the socket
- m_fd_send = m_fd_recv = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (m_fd_send == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
+ *error_ptr = error;
+ if (error.Fail())
return eConnectionStatusError;
- }
-
- m_should_close_fd = true;
-
- // Enable local address reuse
- SetSocketOption (m_fd_send, SOL_SOCKET, SO_REUSEADDR, 1);
-
- struct sockaddr_in sa;
- ::memset (&sa, 0, sizeof (sa));
- sa.sin_family = AF_INET;
- sa.sin_port = htons (port);
- int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
-
- if (inet_pton_result <= 0)
- {
- struct hostent *host_entry = gethostbyname (host_str.c_str());
- if (host_entry)
- host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
- inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
- if (inet_pton_result <= 0)
- {
-
- if (error_ptr)
- {
- if (inet_pton_result == -1)
- error_ptr->SetErrorToErrno();
- else
- error_ptr->SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
- }
- Disconnect (NULL);
-
- return eConnectionStatusError;
- }
- }
-
- if (-1 == ::connect (m_fd_send, (const struct sockaddr *)&sa, sizeof(sa)))
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- Disconnect (NULL);
+ std::unique_ptr<Socket> 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;
- }
- // Keep our TCP packets coming without any delays.
- SetSocketOption (m_fd_send, IPPROTO_TCP, TCP_NODELAY, 1);
- if (error_ptr)
- error_ptr->Clear();
- return eConnectionStatusSuccess;
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError;
}
ConnectionStatus
-ConnectionFileDescriptor::ConnectUDP (const char *host_and_port, Error *error_ptr)
+ConnectionFileDescriptor::ConnectTCP(const char *s, Error *error_ptr)
{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf ("%p ConnectionFileDescriptor::ConnectUDP (host/port = %s)", this, host_and_port);
- Disconnect (NULL);
-
- m_fd_send_type = m_fd_recv_type = eFDTypeSocketUDP;
-
- std::string host_str;
- std::string port_str;
- int32_t port = INT32_MIN;
- if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, error_ptr))
- return eConnectionStatusError;
-
- // 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.
- m_fd_recv = ::socket (AF_INET, SOCK_DGRAM, 0);
- if (m_fd_recv == -1)
- {
- // Socket creation failed...
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- }
- else
- {
- // Socket was created, now lets bind to the requested port
- SocketAddress addr;
- addr.SetToAnyAddress (AF_INET, 0);
-
- if (::bind (m_fd_recv, addr, addr.GetLength()) == -1)
- {
- // Bind failed...
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- Disconnect (NULL);
- }
- }
-
- if (m_fd_recv == -1)
- return eConnectionStatusError;
-
- // At this point we have setup the recieve port, now we need to
- // setup the UDP send socket
-
- struct addrinfo hints;
- struct addrinfo *service_info_list = NULL;
-
- ::memset (&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_DGRAM;
- int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list);
- if (err != 0)
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)",
- host_str.c_str(),
- port_str.c_str(),
- err,
- gai_strerror(err));
- Disconnect (NULL);
- return eConnectionStatusError;
- }
-
- for (struct addrinfo *service_info_ptr = service_info_list;
- service_info_ptr != NULL;
- service_info_ptr = service_info_ptr->ai_next)
- {
- m_fd_send = ::socket (service_info_ptr->ai_family,
- service_info_ptr->ai_socktype,
- service_info_ptr->ai_protocol);
-
- if (m_fd_send != -1)
- {
- *m_udp_send_sockaddr = service_info_ptr;
- break;
- }
- else
- continue;
- }
-
- :: freeaddrinfo (service_info_list);
-
- if (m_fd_send == -1)
- {
- Disconnect (NULL);
- return eConnectionStatusError;
- }
-
+ Socket* socket = nullptr;
+ Error error = Socket::TcpConnect(s, socket);
if (error_ptr)
- error_ptr->Clear();
-
- m_should_close_fd = true;
- return eConnectionStatusSuccess;
-}
-
-#if defined(_WIN32)
-typedef const char * set_socket_option_arg_type;
-typedef char * get_socket_option_arg_type;
-#else // #if defined(_WIN32)
-typedef const void * set_socket_option_arg_type;
-typedef void * get_socket_option_arg_type;
-#endif // #if defined(_WIN32)
-
-int
-ConnectionFileDescriptor::GetSocketOption(int fd, int level, int option_name, int &option_value)
-{
- get_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value);
- socklen_t option_value_size = sizeof(int);
- return ::getsockopt(fd, level, option_name, option_value_p, &option_value_size);
-}
-
-int
-ConnectionFileDescriptor::SetSocketOption(int fd, int level, int option_name, int option_value)
-{
- set_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value);
- return ::setsockopt(fd, level, option_name, option_value_p, sizeof(option_value));
-}
-
-bool
-ConnectionFileDescriptor::SetSocketReceiveTimeout (uint32_t timeout_usec)
-{
- switch (m_fd_recv_type)
- {
- case eFDTypeFile: // Other FD requireing read/write
- break;
-
- case eFDTypeSocket: // Socket requiring send/recv
- case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom
- {
- // Check in case timeout for m_fd has already been set to this value
- if (timeout_usec == m_socket_timeout_usec)
- return true;
- //printf ("ConnectionFileDescriptor::SetSocketReceiveTimeout (timeout_usec = %u)\n", timeout_usec);
-
- struct timeval timeout;
- if (timeout_usec == UINT32_MAX)
- {
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- }
- else if (timeout_usec == 0)
- {
- // Sending in zero does an infinite timeout, so set this as low
- // as we can go to get an effective zero timeout...
- timeout.tv_sec = 0;
- timeout.tv_usec = 1;
- }
- else
- {
- timeout.tv_sec = timeout_usec / TimeValue::MicroSecPerSec;
- timeout.tv_usec = timeout_usec % TimeValue::MicroSecPerSec;
- }
- if (::setsockopt (m_fd_recv, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<get_socket_option_arg_type>(&timeout), sizeof(timeout)) == 0)
- {
- m_socket_timeout_usec = timeout_usec;
- return true;
- }
- }
- }
- return false;
-}
-
-uint16_t
-ConnectionFileDescriptor::GetSocketPort (int fd)
-{
- // We bound to port zero, so we need to figure out which port we actually bound to
- if (fd >= 0)
- {
- SocketAddress sock_addr;
- socklen_t sock_addr_len = sock_addr.GetMaxLength ();
- if (::getsockname (fd, sock_addr, &sock_addr_len) == 0)
- return sock_addr.GetPort ();
- }
- return 0;
+ *error_ptr = error;
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError;
}
-// If the read file descriptor is a socket, then return
-// the port number that is being used by the socket.
-uint16_t
-ConnectionFileDescriptor::GetReadPort () const
+ConnectionStatus
+ConnectionFileDescriptor::ConnectUDP(const char *s, Error *error_ptr)
{
- return ConnectionFileDescriptor::GetSocketPort (m_fd_recv);
+ 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;
}
-// If the write file descriptor is a socket, then return
-// the port number that is being used by the socket.
-uint16_t
-ConnectionFileDescriptor::GetWritePort () const
-{
- return ConnectionFileDescriptor::GetSocketPort (m_fd_send);
-}
-uint16_t
-ConnectionFileDescriptor::GetBoundPort (uint32_t timeout_sec)
+uint16_t ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec)
{
uint16_t bound_port = 0;
if (timeout_sec == UINT32_MAX)
diff --git a/source/Core/ConnectionMachPort.cpp b/source/Core/ConnectionMachPort.cpp
index 4a090dbe5ec8..05ada9872b5b 100644
--- a/source/Core/ConnectionMachPort.cpp
+++ b/source/Core/ConnectionMachPort.cpp
@@ -127,7 +127,7 @@ ConnectionMachPort::BootstrapCheckIn (const char *port, Error *error_ptr)
{
name_t port_name;
int len = snprintf(port_name, sizeof(port_name), "%s", port);
- if (len < sizeof(port_name))
+ if (static_cast<size_t>(len) < sizeof(port_name))
{
kret = ::bootstrap_check_in (bootstrap_port,
port_name,
@@ -160,7 +160,7 @@ ConnectionMachPort::BootstrapLookup (const char *port,
if (port && port[0])
{
- if (::snprintf (port_name, sizeof (port_name), "%s", port) >= sizeof (port_name))
+ if (static_cast<size_t>(::snprintf (port_name, sizeof (port_name), "%s", port)) >= sizeof (port_name))
{
if (error_ptr)
error_ptr->SetErrorString ("port netname is too long");
diff --git a/source/Core/ConnectionSharedMemory.cpp b/source/Core/ConnectionSharedMemory.cpp
index cd708c4868c9..5db3d687cdb2 100644
--- a/source/Core/ConnectionSharedMemory.cpp
+++ b/source/Core/ConnectionSharedMemory.cpp
@@ -24,6 +24,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "llvm/Support/MathExtras.h"
#include "lldb/lldb-private-log.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/Log.h"
@@ -125,8 +126,15 @@ ConnectionSharedMemory::Open (bool create, const char *name, size_t size, Error
#ifdef _WIN32
HANDLE handle;
- if (create)
- handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, (DWORD)(size >> 32), (DWORD)(size), name);
+ if (create) {
+ handle = CreateFileMapping(
+ INVALID_HANDLE_VALUE,
+ NULL,
+ PAGE_READWRITE,
+ llvm::Hi_32(size),
+ llvm::Lo_32(size),
+ name);
+ }
else
handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name);
diff --git a/source/Core/ConstString.cpp b/source/Core/ConstString.cpp
index ce6e51108db5..5657b483a495 100644
--- a/source/Core/ConstString.cpp
+++ b/source/Core/ConstString.cpp
@@ -294,7 +294,10 @@ ConstString::DumpDebug(Stream *s) const
size_t cstr_len = GetLength();
// Only print the parens if we have a non-NULL string
const char *parens = cstr ? "\"" : "";
- s->Printf("%*p: ConstString, string = %s%s%s, length = %" PRIu64, (int)sizeof(void*) * 2, this, parens, cstr, parens, (uint64_t)cstr_len);
+ s->Printf("%*p: ConstString, string = %s%s%s, length = %" PRIu64,
+ static_cast<int>(sizeof(void*) * 2),
+ static_cast<const void*>(this), parens, cstr, parens,
+ static_cast<uint64_t>(cstr_len));
}
void
diff --git a/source/Core/DataBufferHeap.cpp b/source/Core/DataBufferHeap.cpp
index 2c8a865b966c..984b36e54153 100644
--- a/source/Core/DataBufferHeap.cpp
+++ b/source/Core/DataBufferHeap.cpp
@@ -104,6 +104,12 @@ DataBufferHeap::CopyData (const void *src, uint64_t src_len)
}
void
+DataBufferHeap::AppendData (const void *src, uint64_t src_len)
+{
+ m_data.insert(m_data.end(), (uint8_t *)src, (uint8_t *)src + src_len);
+}
+
+void
DataBufferHeap::Clear()
{
buffer_t empty;
diff --git a/source/Core/DataBufferMemoryMap.cpp b/source/Core/DataBufferMemoryMap.cpp
index 008b736ef726..4ca43b89eef1 100644
--- a/source/Core/DataBufferMemoryMap.cpp
+++ b/source/Core/DataBufferMemoryMap.cpp
@@ -18,11 +18,13 @@
#include <sys/mman.h>
#endif
+#include "llvm/Support/MathExtras.h"
+
#include "lldb/Core/DataBufferMemoryMap.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSpec.h"
-#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Core/Log.h"
#include "lldb/lldb-private-log.h"
@@ -89,7 +91,7 @@ DataBufferMemoryMap::Clear()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MMAP));
if (log)
- log->Printf("DataBufferMemoryMap::Clear() m_mmap_addr = %p, m_mmap_size = %zu", m_mmap_addr, m_mmap_size);
+ log->Printf("DataBufferMemoryMap::Clear() m_mmap_addr = %p, m_mmap_size = %" PRIu64 "", m_mmap_addr, (uint64_t)m_mmap_size);
#ifdef _WIN32
UnmapViewOfFile(m_mmap_addr);
#else
@@ -113,7 +115,7 @@ DataBufferMemoryMap::Clear()
size_t
DataBufferMemoryMap::MemoryMapFromFileSpec (const FileSpec* filespec,
lldb::offset_t offset,
- lldb::offset_t length,
+ size_t length,
bool writeable)
{
if (filespec != NULL)
@@ -124,7 +126,7 @@ DataBufferMemoryMap::MemoryMapFromFileSpec (const FileSpec* filespec,
log->Printf("DataBufferMemoryMap::MemoryMapFromFileSpec(file=\"%s\", offset=0x%" PRIx64 ", length=0x%" PRIx64 ", writeable=%i",
filespec->GetPath().c_str(),
offset,
- length,
+ (uint64_t)length,
writeable);
}
char path[PATH_MAX];
@@ -147,16 +149,16 @@ DataBufferMemoryMap::MemoryMapFromFileSpec (const FileSpec* filespec,
Clear();
return 0;
}
-
-
-#ifdef _WIN32
-static size_t win32memmapalignment = 0;
-void LoadWin32MemMapAlignment ()
-{
- SYSTEM_INFO data;
- GetSystemInfo(&data);
- win32memmapalignment = data.dwAllocationGranularity;
-}
+
+
+#ifdef _WIN32
+static size_t win32memmapalignment = 0;
+void LoadWin32MemMapAlignment ()
+{
+ SYSTEM_INFO data;
+ GetSystemInfo(&data);
+ win32memmapalignment = data.dwAllocationGranularity;
+}
#endif
//----------------------------------------------------------------------
@@ -174,7 +176,7 @@ void LoadWin32MemMapAlignment ()
size_t
DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd,
lldb::offset_t offset,
- lldb::offset_t length,
+ size_t length,
bool writeable,
bool fd_is_file)
{
@@ -184,14 +186,10 @@ DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd,
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MMAP|LIBLLDB_LOG_VERBOSE));
if (log)
{
-#ifdef _WIN32
- log->Printf("DataBufferMemoryMap::MemoryMapFromFileSpec(fd=%p, offset=0x%" PRIx64 ", length=0x%" PRIx64 ", writeable=%i, fd_is_file=%i)",
-#else
- log->Printf("DataBufferMemoryMap::MemoryMapFromFileSpec(fd=%i, offset=0x%" PRIx64 ", length=0x%" PRIx64 ", writeable=%i, fd_is_file=%i)",
-#endif
+ log->Printf("DataBufferMemoryMap::MemoryMapFromFileDescriptor(fd=%i, offset=0x%" PRIx64 ", length=0x%" PRIx64 ", writeable=%i, fd_is_file=%i)",
fd,
offset,
- length,
+ (uint64_t)length,
writeable,
fd_is_file);
}
@@ -199,16 +197,13 @@ DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd,
HANDLE handle = (HANDLE)_get_osfhandle(fd);
DWORD file_size_low, file_size_high;
file_size_low = GetFileSize(handle, &file_size_high);
- const size_t file_size = (file_size_high << 32) | file_size_low;
- const size_t max_bytes_available = file_size - offset;
- if (length == SIZE_MAX)
- {
- length = max_bytes_available;
- }
- else if (length > max_bytes_available)
+ const lldb::offset_t file_size = llvm::Make_64(file_size_high, file_size_low);
+ const lldb::offset_t max_bytes_available = file_size - offset;
+ const size_t max_bytes_mappable = (size_t)std::min<lldb::offset_t>(SIZE_MAX, max_bytes_available);
+ if (length == SIZE_MAX || length > max_bytes_mappable)
{
// Cap the length if too much data was requested
- length = max_bytes_available;
+ length = max_bytes_mappable;
}
if (length > 0)
@@ -216,23 +211,23 @@ DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd,
HANDLE fileMapping = CreateFileMapping(handle, NULL, writeable ? PAGE_READWRITE : PAGE_READONLY, file_size_high, file_size_low, NULL);
if (fileMapping != NULL)
{
- if (win32memmapalignment == 0) LoadWin32MemMapAlignment();
- lldb::offset_t realoffset = offset;
- lldb::offset_t delta = 0;
- if (realoffset % win32memmapalignment != 0) {
- realoffset = realoffset / win32memmapalignment * win32memmapalignment;
- delta = offset - realoffset;
- }
-
- LPVOID data = MapViewOfFile(fileMapping, writeable ? FILE_MAP_WRITE : FILE_MAP_READ, 0, realoffset, length + delta);
- m_mmap_addr = (uint8_t *)data;
- if (!data) {
- Error error;
- error.SetErrorToErrno ();
+ if (win32memmapalignment == 0) LoadWin32MemMapAlignment();
+ lldb::offset_t realoffset = offset;
+ lldb::offset_t delta = 0;
+ if (realoffset % win32memmapalignment != 0) {
+ realoffset = realoffset / win32memmapalignment * win32memmapalignment;
+ delta = offset - realoffset;
+ }
+
+ LPVOID data = MapViewOfFile(fileMapping, writeable ? FILE_MAP_WRITE : FILE_MAP_READ, 0, realoffset, length + delta);
+ m_mmap_addr = (uint8_t *)data;
+ if (!data) {
+ Error error;
+ error.SetErrorToErrno ();
} else {
- m_data = m_mmap_addr + delta;
- m_size = length;
- }
+ m_data = m_mmap_addr + delta;
+ m_size = length;
+ }
CloseHandle(fileMapping);
}
}
@@ -240,7 +235,8 @@ DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd,
struct stat stat;
if (::fstat(fd, &stat) == 0)
{
- if (S_ISREG(stat.st_mode) && (stat.st_size > offset))
+ if (S_ISREG(stat.st_mode) &&
+ (stat.st_size > static_cast<off_t>(offset)))
{
const size_t max_bytes_available = stat.st_size - offset;
if (length == SIZE_MAX)
@@ -272,7 +268,7 @@ DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd,
if (error.GetError() == EINVAL)
{
// We may still have a shot at memory mapping if we align things correctly
- size_t page_offset = offset % Host::GetPageSize();
+ size_t page_offset = offset % HostInfo::GetPageSize();
if (page_offset != 0)
{
m_mmap_addr = (uint8_t *)::mmap(NULL, length + page_offset, prot, flags, fd, offset - page_offset);
@@ -311,8 +307,8 @@ DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd,
if (log)
{
- log->Printf("DataBufferMemoryMap::MemoryMapFromFileSpec() m_mmap_addr = %p, m_mmap_size = %zu, error = %s",
- m_mmap_addr, m_mmap_size, error.AsCString());
+ log->Printf("DataBufferMemoryMap::MemoryMapFromFileSpec() m_mmap_addr = %p, m_mmap_size = %" PRIu64 ", error = %s",
+ m_mmap_addr, (uint64_t)m_mmap_size, error.AsCString());
}
}
}
diff --git a/source/Core/DataExtractor.cpp b/source/Core/DataExtractor.cpp
index b42c6ff31449..a0958bd6b1c6 100644
--- a/source/Core/DataExtractor.cpp
+++ b/source/Core/DataExtractor.cpp
@@ -52,7 +52,7 @@ ReadInt16(const unsigned char* ptr, offset_t offset)
}
static inline uint32_t
-ReadInt32 (const unsigned char* ptr, offset_t offset)
+ReadInt32 (const unsigned char* ptr, offset_t offset = 0)
{
uint32_t value;
memcpy (&value, ptr + offset, 4);
@@ -60,7 +60,7 @@ ReadInt32 (const unsigned char* ptr, offset_t offset)
}
static inline uint64_t
-ReadInt64(const unsigned char* ptr, offset_t offset)
+ReadInt64(const unsigned char* ptr, offset_t offset = 0)
{
uint64_t value;
memcpy (&value, ptr + offset, 8);
@@ -75,22 +75,6 @@ ReadInt16(const void* ptr)
return value;
}
-static inline uint32_t
-ReadInt32 (const void* ptr)
-{
- uint32_t value;
- memcpy (&value, ptr, 4);
- return value;
-}
-
-static inline uint64_t
-ReadInt64(const void* ptr)
-{
- uint64_t value;
- memcpy (&value, ptr, 8);
- return value;
-}
-
static inline uint16_t
ReadSwapInt16(const unsigned char* ptr, offset_t offset)
{
@@ -409,7 +393,7 @@ DataExtractor::GetU8 (offset_t *offset_ptr) const
//
// RETURNS the non-NULL buffer pointer upon successful extraction of
// all the requested bytes, or NULL when the data is not available in
-// the buffer due to being out of bounds, or unsufficient data.
+// the buffer due to being out of bounds, or insufficient data.
//----------------------------------------------------------------------
void *
DataExtractor::GetU8 (offset_t *offset_ptr, void *dst, uint32_t count) const
@@ -490,7 +474,7 @@ DataExtractor::GetU64_unchecked (offset_t *offset_ptr) const
//
// RETURNS the non-NULL buffer pointer upon successful extraction of
// all the requested bytes, or NULL when the data is not available
-// in the buffer due to being out of bounds, or unsufficient data.
+// in the buffer due to being out of bounds, or insufficient data.
//----------------------------------------------------------------------
void *
DataExtractor::GetU16 (offset_t *offset_ptr, void *void_dst, uint32_t count) const
@@ -553,7 +537,7 @@ DataExtractor::GetU32 (offset_t *offset_ptr) const
//
// RETURNS the non-NULL buffer pointer upon successful extraction of
// all the requested bytes, or NULL when the data is not available
-// in the buffer due to being out of bounds, or unsufficient data.
+// in the buffer due to being out of bounds, or insufficient data.
//----------------------------------------------------------------------
void *
DataExtractor::GetU32 (offset_t *offset_ptr, void *void_dst, uint32_t count) const
@@ -1124,7 +1108,7 @@ DataExtractor::CopyByteOrderedData (offset_t src_offset,
// follows the NULL terminator byte.
//
// If the offset pointed to by "offset_ptr" is out of bounds, or if
-// "length" is non-zero and there aren't enough avaialable
+// "length" is non-zero and there aren't enough available
// bytes, NULL will be returned and "offset_ptr" will not be
// updated.
//----------------------------------------------------------------------
@@ -1150,7 +1134,7 @@ DataExtractor::GetCStr (offset_t *offset_ptr) const
// We reached the end of the data without finding a NULL C string
// terminator. Fall through and return NULL otherwise anyone that
- // would have used the result as a C string can wonder into
+ // would have used the result as a C string can wander into
// unknown memory...
}
return NULL;
@@ -1491,7 +1475,7 @@ DataExtractor::Dump (Stream *s,
if (item_format == eFormatBytesWithASCII && offset > line_start_offset)
{
s->Printf("%*s", static_cast<int>((num_per_line - (offset - line_start_offset)) * 3 + 2), "");
- Dump(s, line_start_offset, eFormatCharPrintable, 1, offset - line_start_offset, LLDB_INVALID_OFFSET, LLDB_INVALID_ADDRESS, 0, 0);
+ Dump(s, line_start_offset, eFormatCharPrintable, 1, offset - line_start_offset, SIZE_MAX, LLDB_INVALID_ADDRESS, 0, 0);
}
s->EOL();
}
@@ -1516,7 +1500,7 @@ DataExtractor::Dump (Stream *s,
s->Printf ("%s", GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset) ? "true" : "false");
else
{
- s->Printf("error: unsupported byte size (%zu) for boolean format", item_byte_size);
+ s->Printf("error: unsupported byte size (%" PRIu64 ") for boolean format", (uint64_t)item_byte_size);
return offset;
}
break;
@@ -1725,7 +1709,7 @@ DataExtractor::Dump (Stream *s,
}
else
{
- s->Printf("error: unsupported byte size (%zu) for complex integer format", item_byte_size);
+ s->Printf("error: unsupported byte size (%" PRIu64 ") for complex integer format", (uint64_t)item_byte_size);
return offset;
}
}
@@ -1757,7 +1741,7 @@ DataExtractor::Dump (Stream *s,
}
else
{
- s->Printf("error: unsupported byte size (%zu) for complex float format", item_byte_size);
+ s->Printf("error: unsupported byte size (%" PRIu64 ") for complex float format", (uint64_t)item_byte_size);
return offset;
}
break;
@@ -1839,14 +1823,11 @@ DataExtractor::Dump (Stream *s,
else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy))
{
llvm::APInt apint;
- switch (target_sp->GetArchitecture().GetCore())
+ switch (target_sp->GetArchitecture().GetMachine())
{
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- case ArchSpec::eCore_x86_64_x86_64:
- case ArchSpec::eCore_x86_64_x86_64h:
- // clang will assert when contructing the apfloat if we use a 16 byte integer value
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ // clang will assert when constructing the apfloat if we use a 16 byte integer value
if (GetAPInt (*this, &offset, 10, apint))
{
llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->LongDoubleTy), apint);
@@ -1909,7 +1890,7 @@ DataExtractor::Dump (Stream *s,
}
else
{
- s->Printf("error: unsupported byte size (%zu) for float format", item_byte_size);
+ s->Printf("error: unsupported byte size (%" PRIu64 ") for float format", (uint64_t)item_byte_size);
return offset;
}
ss.flush();
@@ -1973,7 +1954,7 @@ DataExtractor::Dump (Stream *s,
}
else
{
- s->Printf("error: unsupported byte size (%zu) for hex float format", item_byte_size);
+ s->Printf("error: unsupported byte size (%" PRIu64 ") for hex float format", (uint64_t)item_byte_size);
return offset;
}
break;
@@ -2058,7 +2039,7 @@ DataExtractor::Dump (Stream *s,
if (item_format == eFormatBytesWithASCII && offset > line_start_offset)
{
s->Printf("%*s", static_cast<int>((num_per_line - (offset - line_start_offset)) * 3 + 2), "");
- Dump(s, line_start_offset, eFormatCharPrintable, 1, offset - line_start_offset, LLDB_INVALID_OFFSET, LLDB_INVALID_ADDRESS, 0, 0);
+ Dump(s, line_start_offset, eFormatCharPrintable, 1, offset - line_start_offset, SIZE_MAX, LLDB_INVALID_ADDRESS, 0, 0);
}
return offset; // Return the offset at which we ended up
}
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
index 34e0e329f092..178296347677 100644
--- a/source/Core/Debugger.cpp
+++ b/source/Core/Debugger.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
+#include "llvm/ADT/StringRef.h"
#include "lldb/lldb-private.h"
#include "lldb/Core/ConnectionFileDescriptor.h"
@@ -26,12 +27,14 @@
#include "lldb/Core/StreamCallback.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Core/StructuredData.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/FormatManager.h"
-#include "lldb/Host/DynamicLibrary.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Terminal.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionValueSInt64.h"
@@ -50,6 +53,8 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/AnsiTerminal.h"
+#include "llvm/Support/DynamicLibrary.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -72,7 +77,7 @@ static DebuggerList &
GetDebuggerList()
{
// hide the static debugger list inside a singleton accessor to avoid
- // global init contructors
+ // global init constructors
static DebuggerList g_list;
return g_list;
}
@@ -104,8 +109,11 @@ g_language_enumerators[] =
FILE_AND_LINE\
"{, name = '${thread.name}'}"\
"{, queue = '${thread.queue}'}"\
+ "{, activity = '${thread.info.activity.name}'}" \
+ "{, ${thread.info.trace_messages} messages}" \
"{, stop reason = ${thread.stop-reason}}"\
"{\\nReturn value: ${thread.return-value}}"\
+ "{\\nCompleted expression: ${thread.completed-expression}}"\
"\\n"
#define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\
@@ -406,10 +414,10 @@ Debugger::LoadPlugin (const FileSpec& spec, Error& error)
{
if (g_load_plugin_callback)
{
- lldb::DynamicLibrarySP dynlib_sp = g_load_plugin_callback (shared_from_this(), spec, error);
- if (dynlib_sp)
+ llvm::sys::DynamicLibrary dynlib = g_load_plugin_callback (shared_from_this(), spec, error);
+ if (dynlib.isValid())
{
- m_loaded_plugins.push_back(dynlib_sp);
+ m_loaded_plugins.push_back(dynlib);
return true;
}
}
@@ -470,7 +478,7 @@ LoadPluginCallback
{
// Try and recurse into anything that a directory or symbolic link.
// We must also do this for unknown as sometimes the directory enumeration
- // might be enurating a file system that doesn't have correct file type
+ // might be enumerating a file system that doesn't have correct file type
// information.
return FileSpec::eEnumerateDirectoryResultEnter;
}
@@ -486,7 +494,7 @@ Debugger::InstanceInitialize ()
const bool find_files = true;
const bool find_other = true;
char dir_path[PATH_MAX];
- if (Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec))
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec))
{
if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path)))
{
@@ -498,8 +506,8 @@ Debugger::InstanceInitialize ()
this);
}
}
-
- if (Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec))
+
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec))
{
if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path)))
{
@@ -629,8 +637,7 @@ Debugger::Debugger (lldb::LogOutputCallback log_callback, void *baton) :
m_instance_name (),
m_loaded_plugins (),
m_event_handler_thread (LLDB_INVALID_HOST_THREAD),
- m_io_handler_thread (LLDB_INVALID_HOST_THREAD),
- m_event_handler_thread_alive(false)
+ m_io_handler_thread (LLDB_INVALID_HOST_THREAD)
{
char instance_cstr[256];
snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
@@ -696,6 +703,8 @@ Debugger::Clear()
m_terminal_state.Clear();
if (m_input_file_sp)
m_input_file_sp->GetFile().Close ();
+
+ m_command_interpreter_ap->Clear();
}
bool
@@ -896,9 +905,29 @@ Debugger::RunIOHandler (const IOHandlerSP& reader_sp)
{
Mutex::Locker locker (m_input_reader_stack.GetMutex());
PushIOHandler (reader_sp);
- reader_sp->Activate();
- reader_sp->Run();
- PopIOHandler (reader_sp);
+
+ IOHandlerSP top_reader_sp = reader_sp;
+ while (top_reader_sp)
+ {
+ top_reader_sp->Activate();
+ top_reader_sp->Run();
+ top_reader_sp->Deactivate();
+
+ if (top_reader_sp.get() == reader_sp.get())
+ {
+ if (PopIOHandler (reader_sp))
+ break;
+ }
+
+ while (1)
+ {
+ top_reader_sp = m_input_reader_stack.Top();
+ if (top_reader_sp && top_reader_sp->GetIsDone())
+ m_input_reader_stack.Pop();
+ else
+ break;
+ }
+ }
}
void
@@ -960,13 +989,17 @@ Debugger::PushIOHandler (const IOHandlerSP& reader_sp)
// Got the current top input reader...
IOHandlerSP top_reader_sp (m_input_reader_stack.Top());
- // Push our new input reader
- m_input_reader_stack.Push (reader_sp);
+ // Don't push the same IO handler twice...
+ if (reader_sp.get() != top_reader_sp.get())
+ {
+ // Push our new input reader
+ m_input_reader_stack.Push (reader_sp);
- // Interrupt the top input reader to it will exit its Run() function
- // and let this new input reader take over
- if (top_reader_sp)
- top_reader_sp->Deactivate();
+ // Interrupt the top input reader to it will exit its Run() function
+ // and let this new input reader take over
+ if (top_reader_sp)
+ top_reader_sp->Deactivate();
+ }
}
bool
@@ -977,7 +1010,7 @@ Debugger::PopIOHandler (const IOHandlerSP& pop_reader_sp)
Mutex::Locker locker (m_input_reader_stack.GetMutex());
// The reader on the stop of the stack is done, so let the next
- // read on the stack referesh its prompt and if there is one...
+ // read on the stack refresh its prompt and if there is one...
if (!m_input_reader_stack.IsEmpty())
{
IOHandlerSP reader_sp(m_input_reader_stack.Top());
@@ -985,6 +1018,7 @@ Debugger::PopIOHandler (const IOHandlerSP& pop_reader_sp)
if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
{
reader_sp->Deactivate();
+ reader_sp->Cancel();
m_input_reader_stack.Pop ();
reader_sp = m_input_reader_stack.Top();
@@ -1085,6 +1119,7 @@ Debugger::FindDebuggerWithID (lldb::user_id_t id)
return debugger_sp;
}
+#if 0
static void
TestPromptFormats (StackFrame *frame)
{
@@ -1145,6 +1180,7 @@ TestPromptFormats (StackFrame *frame)
printf ("what we got: %s\n", s.GetData());
}
}
+#endif
static bool
ScanFormatDescriptor (const char* var_name_begin,
@@ -1421,6 +1457,96 @@ IsTokenWithFormat(const char *var_name_begin, const char *var, std::string &form
return false;
}
+// Find information for the "thread.info.*" specifiers in a format string
+static bool
+FormatThreadExtendedInfoRecurse
+(
+ const char *var_name_begin,
+ StructuredData::ObjectSP thread_info_dictionary,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ Stream &s
+)
+{
+ bool var_success = false;
+ std::string token_format;
+
+ llvm::StringRef var_name(var_name_begin);
+ size_t percent_idx = var_name.find('%');
+ size_t close_curly_idx = var_name.find('}');
+ llvm::StringRef path = var_name;
+ llvm::StringRef formatter = var_name;
+
+ // 'path' will be the dot separated list of objects to transverse up until we hit
+ // a close curly brace, a percent sign, or an end of string.
+ if (percent_idx != llvm::StringRef::npos || close_curly_idx != llvm::StringRef::npos)
+ {
+ if (percent_idx != llvm::StringRef::npos && close_curly_idx != llvm::StringRef::npos)
+ {
+ if (percent_idx < close_curly_idx)
+ {
+ path = var_name.slice(0, percent_idx);
+ formatter = var_name.substr (percent_idx);
+ }
+ else
+ {
+ path = var_name.slice(0, close_curly_idx);
+ formatter = var_name.substr (close_curly_idx);
+ }
+ }
+ else if (percent_idx != llvm::StringRef::npos)
+ {
+ path = var_name.slice(0, percent_idx);
+ formatter = var_name.substr (percent_idx);
+ }
+ else if (close_curly_idx != llvm::StringRef::npos)
+ {
+ path = var_name.slice(0, close_curly_idx);
+ formatter = var_name.substr (close_curly_idx);
+ }
+ }
+
+ StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path);
+
+ if (value.get())
+ {
+ if (value->GetType() == StructuredData::Type::eTypeInteger)
+ {
+ if (IsTokenWithFormat (formatter.str().c_str(), "", token_format, "0x%4.4" PRIx64, exe_ctx, sc))
+ {
+ s.Printf(token_format.c_str(), value->GetAsInteger()->GetValue());
+ var_success = true;
+ }
+ }
+ else if (value->GetType() == StructuredData::Type::eTypeFloat)
+ {
+ s.Printf ("%f", value->GetAsFloat()->GetValue());
+ var_success = true;
+ }
+ else if (value->GetType() == StructuredData::Type::eTypeString)
+ {
+ s.Printf("%s", value->GetAsString()->GetValue().c_str());
+ var_success = true;
+ }
+ else if (value->GetType() == StructuredData::Type::eTypeArray)
+ {
+ if (value->GetAsArray()->GetSize() > 0)
+ {
+ s.Printf ("%zu", value->GetAsArray()->GetSize());
+ var_success = true;
+ }
+ }
+ else if (value->GetType() == StructuredData::Type::eTypeDictionary)
+ {
+ s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
+ var_success = true;
+ }
+ }
+
+ return var_success;
+}
+
+
static bool
FormatPromptRecurse
(
@@ -1678,6 +1804,13 @@ FormatPromptRecurse
do_deref_pointer = false;
}
+ if (!target)
+ {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression");
+ break;
+ }
+
// we do not want to use the summary for a bitfield of type T:n
// if we were originally dealing with just a T - that would get
// us into an endless recursion
@@ -1945,6 +2078,19 @@ FormatPromptRecurse
}
}
}
+ else if (IsToken (var_name_begin, "completed-expression}"))
+ {
+ StopInfoSP stop_info_sp = thread->GetStopInfo ();
+ if (stop_info_sp && stop_info_sp->IsValid())
+ {
+ ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp);
+ if (expression_var_sp && expression_var_sp->GetValueObject())
+ {
+ expression_var_sp->GetValueObject()->Dump(s);
+ var_success = true;
+ }
+ }
+ }
else if (IsToken (var_name_begin, "script:"))
{
var_name_begin += ::strlen("script:");
@@ -1953,6 +2099,15 @@ FormatPromptRecurse
if (RunScriptFormatKeyword (s, script_interpreter, thread, script_name))
var_success = true;
}
+ else if (IsToken (var_name_begin, "info."))
+ {
+ var_name_begin += ::strlen("info.");
+ StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
+ if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary)
+ {
+ var_success = FormatThreadExtendedInfoRecurse (var_name_begin, object_sp, sc, exe_ctx, s);
+ }
+ }
}
}
}
@@ -2205,7 +2360,29 @@ FormatPromptRecurse
if (args.GetSize() > 0)
{
const char *open_paren = strchr (cstr, '(');
- const char *close_paren = NULL;
+ const char *close_paren = nullptr;
+ const char *generic = strchr(cstr, '<');
+ // if before the arguments list begins there is a template sign
+ // then scan to the end of the generic args before you try to find
+ // the arguments list
+ if (generic && open_paren && generic < open_paren)
+ {
+ int generic_depth = 1;
+ ++generic;
+ for (;
+ *generic && generic_depth > 0;
+ generic++)
+ {
+ if (*generic == '<')
+ generic_depth++;
+ if (*generic == '>')
+ generic_depth--;
+ }
+ if (*generic)
+ open_paren = strchr(generic, '(');
+ else
+ open_paren = nullptr;
+ }
if (open_paren)
{
if (IsToken (open_paren, "(anonymous namespace)"))
@@ -2228,16 +2405,30 @@ FormatPromptRecurse
const size_t num_args = args.GetSize();
for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx)
{
+ std::string buffer;
+
VariableSP var_sp (args.GetVariableAtIndex (arg_idx));
ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp));
+ const char *var_representation = nullptr;
const char *var_name = var_value_sp->GetName().GetCString();
- const char *var_value = var_value_sp->GetValueAsCString();
+ if (var_value_sp->GetClangType().IsAggregateType() &&
+ DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get()))
+ {
+ static StringSummaryFormat format(TypeSummaryImpl::Flags()
+ .SetHideItemNames(false)
+ .SetShowMembersOneLiner(true),
+ "");
+ format.FormatObject(var_value_sp.get(), buffer);
+ var_representation = buffer.c_str();
+ }
+ else
+ var_representation = var_value_sp->GetValueAsCString();
if (arg_idx > 0)
s.PutCString (", ");
if (var_value_sp->GetError().Success())
{
- if (var_value)
- s.Printf ("%s=%s", var_name, var_value);
+ if (var_representation)
+ s.Printf ("%s=%s", var_name, var_representation);
else
s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString());
}
@@ -2769,36 +2960,30 @@ Debugger::HandleProcessEvent (const EventSP &event_sp)
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();
- bool top_io_handler_hid = false;
- if (gui_enabled == false)
- top_io_handler_hid = HideTopIOHandler();
- assert (process_sp);
-
- if (event_type & Process::eBroadcastBitSTDOUT)
+ if (!gui_enabled)
{
- // The process has stdout available, get it and write it out to the
- // appropriate place.
- if (top_io_handler_hid)
- GetProcessSTDOUT (process_sp.get(), NULL);
- }
- else if (event_type & Process::eBroadcastBitSTDERR)
- {
- // The process has stderr available, get it and write it out to the
- // appropriate place.
- if (top_io_handler_hid)
- GetProcessSTDERR (process_sp.get(), NULL);
- }
- else if (event_type & Process::eBroadcastBitStateChanged)
- {
- // Drain all stout and stderr so we don't see any output come after
- // we print our prompts
- if (top_io_handler_hid)
+ bool pop_process_io_handler = false;
+ assert (process_sp);
+
+ if (event_type & Process::eBroadcastBitSTDOUT || event_type & Process::eBroadcastBitStateChanged)
{
- StreamFileSP stream_sp (GetOutputFile());
- GetProcessSTDOUT (process_sp.get(), stream_sp.get());
- GetProcessSTDERR (process_sp.get(), NULL);
+ 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());
@@ -2815,9 +3000,12 @@ Debugger::HandleProcessEvent (const EventSP &event_sp)
case eStateStepping:
case eStateDetached:
{
- stream_sp->Printf("Process %" PRIu64 " %s\n",
- process_sp->GetID(),
- StateAsCString (event_state));
+ output_stream.Printf("Process %" PRIu64 " %s\n",
+ process_sp->GetID(),
+ StateAsCString (event_state));
+
+ if (event_state == eStateDetached)
+ pop_process_io_handler = true;
}
break;
@@ -2826,7 +3014,8 @@ Debugger::HandleProcessEvent (const EventSP &event_sp)
break;
case eStateExited:
- process_sp->GetStatus(*stream_sp);
+ process_sp->GetStatus(output_stream);
+ pop_process_io_handler = true;
break;
case eStateStopped:
@@ -2842,86 +3031,91 @@ Debugger::HandleProcessEvent (const EventSP &event_sp)
if (num_reasons == 1)
{
const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), 0);
- stream_sp->Printf("Process %" PRIu64 " stopped and restarted: %s\n",
- process_sp->GetID(),
- reason ? reason : "<UNKNOWN REASON>");
+ output_stream.Printf("Process %" PRIu64 " stopped and restarted: %s\n",
+ process_sp->GetID(),
+ reason ? reason : "<UNKNOWN REASON>");
}
else
{
- stream_sp->Printf("Process %" PRIu64 " stopped and restarted, reasons:\n",
- process_sp->GetID());
+ 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);
- stream_sp->Printf("\t%s\n", reason ? reason : "<UNKNOWN REASON>");
+ output_stream.Printf("\t%s\n", reason ? reason : "<UNKNOWN REASON>");
}
}
}
}
else
{
- // Lock the thread list so it doesn't change on us
- 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)
+ // Lock the thread list so it doesn't change on us, this is the scope for the locker:
{
- // 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)
+ 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)
{
- thread = thread_list.GetThreadAtIndex(i);
- StopReason thread_stop_reason = thread->GetStopReason();
- switch (thread_stop_reason)
+ // 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)
{
- 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;
+ 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;
+ if (plan_thread)
+ thread_list.SetSelectedThreadByID (plan_thread->GetID());
+ else if (other_thread)
+ thread_list.SetSelectedThreadByID (other_thread->GetID());
else
- thread = thread_list.GetThreadAtIndex(0);
-
- if (thread)
- thread_list.SetSelectedThreadByID (thread->GetID());
+ {
+ 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())
{
@@ -2929,8 +3123,8 @@ Debugger::HandleProcessEvent (const EventSP &event_sp)
const uint32_t start_frame = 0;
const uint32_t num_frames = 1;
const uint32_t num_frames_with_source = 1;
- process_sp->GetStatus(*stream_sp);
- process_sp->GetThreadStatus (*stream_sp,
+ process_sp->GetStatus(output_stream);
+ process_sp->GetThreadStatus (output_stream,
only_threads_with_stop_reason,
start_frame,
num_frames,
@@ -2940,20 +3134,49 @@ Debugger::HandleProcessEvent (const EventSP &event_sp)
{
uint32_t target_idx = GetTargetList().GetIndexOfTarget(process_sp->GetTarget().shared_from_this());
if (target_idx != UINT32_MAX)
- stream_sp->Printf ("Target %d: (", target_idx);
+ output_stream.Printf ("Target %d: (", target_idx);
else
- stream_sp->Printf ("Target <unknown index>: (");
- process_sp->GetTarget().Dump (stream_sp.get(), eDescriptionLevelBrief);
- stream_sp->Printf (") stopped.\n");
+ output_stream.Printf ("Target <unknown index>: (");
+ process_sp->GetTarget().Dump (&output_stream, eDescriptionLevelBrief);
+ output_stream.Printf (") stopped.\n");
}
+
+ // Pop the process IO handler
+ pop_process_io_handler = true;
}
break;
}
}
- }
- if (top_io_handler_hid)
- RefreshTopIOHandler();
+ 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();
+
+ if (output_stream.GetSize())
+ {
+ StreamFileSP output_stream_sp (GetOutputFile());
+ if (output_stream_sp)
+ output_stream_sp->Write (output_stream.GetData(), output_stream.GetSize());
+ }
+
+ if (error_stream.GetSize())
+ {
+ StreamFileSP error_stream_sp (GetErrorFile());
+ if (error_stream_sp)
+ error_stream_sp->Write (error_stream.GetData(), error_stream.GetSize());
+ }
+
+ if (top_io_handler_hid)
+ RefreshTopIOHandler();
+ }
+
+ if (pop_process_io_handler)
+ process_sp->PopProcessIOHandler();
+ }
}
void
diff --git a/source/Core/EmulateInstruction.cpp b/source/Core/EmulateInstruction.cpp
index bf6c6d88b563..8349f54de4c7 100644
--- a/source/Core/EmulateInstruction.cpp
+++ b/source/Core/EmulateInstruction.cpp
@@ -75,7 +75,7 @@ EmulateInstruction::ReadRegister (const RegisterInfo *reg_info, RegisterValue& r
}
bool
-EmulateInstruction::ReadRegister (uint32_t reg_kind, uint32_t reg_num, RegisterValue& reg_value)
+EmulateInstruction::ReadRegister (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterValue& reg_value)
{
RegisterInfo reg_info;
if (GetRegisterInfo(reg_kind, reg_num, reg_info))
@@ -84,7 +84,7 @@ EmulateInstruction::ReadRegister (uint32_t reg_kind, uint32_t reg_num, RegisterV
}
uint64_t
-EmulateInstruction::ReadRegisterUnsigned (uint32_t reg_kind,
+EmulateInstruction::ReadRegisterUnsigned (lldb::RegisterKind reg_kind,
uint32_t reg_num,
uint64_t fail_value,
bool *success_ptr)
@@ -122,7 +122,7 @@ EmulateInstruction::WriteRegister (const Context &context,
bool
EmulateInstruction::WriteRegister (const Context &context,
- uint32_t reg_kind,
+ lldb::RegisterKind reg_kind,
uint32_t reg_num,
const RegisterValue& reg_value)
{
@@ -135,7 +135,7 @@ EmulateInstruction::WriteRegister (const Context &context,
bool
EmulateInstruction::WriteRegisterUnsigned (const Context &context,
- uint32_t reg_kind,
+ lldb::RegisterKind reg_kind,
uint32_t reg_num,
uint64_t uint_value)
{
@@ -392,7 +392,8 @@ EmulateInstruction::ReadRegisterDefault (EmulateInstruction *instruction,
{
StreamFile strm (stdout, false);
strm.Printf (" Read Register (%s)\n", reg_info->name);
- uint32_t reg_kind, reg_num;
+ lldb::RegisterKind reg_kind;
+ uint32_t reg_num;
if (GetBestRegisterKindAndNumber (reg_info, reg_kind, reg_num))
reg_value.SetUInt64((uint64_t)reg_kind << 24 | reg_num);
else
@@ -608,7 +609,7 @@ EmulateInstruction::SetInstruction (const Opcode &opcode, const Address &inst_ad
bool
EmulateInstruction::GetBestRegisterKindAndNumber (const RegisterInfo *reg_info,
- uint32_t &reg_kind,
+ lldb::RegisterKind &reg_kind,
uint32_t &reg_num)
{
// Generic and DWARF should be the two most popular register kinds when
@@ -653,7 +654,8 @@ EmulateInstruction::GetBestRegisterKindAndNumber (const RegisterInfo *reg_info,
uint32_t
EmulateInstruction::GetInternalRegisterNumber (RegisterContext *reg_ctx, const RegisterInfo &reg_info)
{
- uint32_t reg_kind, reg_num;
+ lldb::RegisterKind reg_kind;
+ uint32_t reg_num;
if (reg_ctx && GetBestRegisterKindAndNumber (&reg_info, reg_kind, reg_num))
return reg_ctx->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num);
return LLDB_INVALID_REGNUM;
diff --git a/source/Core/Error.cpp b/source/Core/Error.cpp
index 7aabe5b386d4..03cfd41b288d 100644
--- a/source/Core/Error.cpp
+++ b/source/Core/Error.cpp
@@ -21,7 +21,7 @@
#include <cerrno>
#include <cstdarg>
-#if defined (__arm__) && defined (__APPLE__)
+#if (defined (__arm__) || defined (__arm64__) || defined (__aarch64__)) && defined (__APPLE__)
#include <SpringBoardServices/SpringBoardServer.h>
#endif
@@ -264,6 +264,35 @@ Error::SetMachError (uint32_t err)
m_string.clear();
}
+void
+Error::SetExpressionError (lldb::ExpressionResults result, const char *mssg)
+{
+ m_code = result;
+ m_type = eErrorTypeExpression;
+ m_string = mssg;
+}
+
+int
+Error::SetExpressionErrorWithFormat (lldb::ExpressionResults result, const char *format, ...)
+{
+ int length = 0;
+
+ if (format && format[0])
+ {
+ va_list args;
+ va_start (args, format);
+ length = SetErrorStringWithVarArg (format, args);
+ va_end (args);
+ }
+ else
+ {
+ m_string.clear();
+ }
+ m_code = result;
+ m_type = eErrorTypeExpression;
+ return length;
+}
+
//----------------------------------------------------------------------
// Set accesssor for the error value and type.
//----------------------------------------------------------------------
diff --git a/source/Core/Event.cpp b/source/Core/Event.cpp
index 2d4899dd6dcb..bf5ff222a122 100644
--- a/source/Core/Event.cpp
+++ b/source/Core/Event.cpp
@@ -57,20 +57,19 @@ Event::Dump (Stream *s) const
StreamString event_name;
if (m_broadcaster->GetEventNames (event_name, m_type, false))
s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x (%s), data = ",
- this,
- m_broadcaster,
+ static_cast<const void*>(this),
+ static_cast<void*>(m_broadcaster),
m_broadcaster->GetBroadcasterName().GetCString(),
- m_type,
- event_name.GetString().c_str());
+ m_type, event_name.GetString().c_str());
else
s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x, data = ",
- this,
- m_broadcaster,
- m_broadcaster->GetBroadcasterName().GetCString(),
- m_type);
+ static_cast<const void*>(this),
+ static_cast<void*>(m_broadcaster),
+ m_broadcaster->GetBroadcasterName().GetCString(), m_type);
}
else
- s->Printf("%p Event: broadcaster = NULL, type = 0x%8.8x, data = ", this, m_type);
+ s->Printf("%p Event: broadcaster = NULL, type = 0x%8.8x, data = ",
+ static_cast<const void*>(this), m_type);
if (m_data_ap.get() == NULL)
s->Printf ("<NULL>");
diff --git a/source/Core/FastDemangle.cpp b/source/Core/FastDemangle.cpp
new file mode 100644
index 000000000000..00a75425b689
--- /dev/null
+++ b/source/Core/FastDemangle.cpp
@@ -0,0 +1,2203 @@
+//===-- FastDemangle.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+//#define DEBUG_FAILURES 1
+//#define DEBUG_SUBSTITUTIONS 1
+//#define DEBUG_TEMPLATE_ARGS 1
+//#define DEBUG_HIGHWATER 1
+//#define DEBUG_REORDERING 1
+
+namespace {
+
+/// @brief Represents the collection of qualifiers on a type
+
+enum Qualifiers
+{
+ QualifierNone = 0,
+ QualifierConst = 1,
+ QualifierRestrict = 2,
+ QualifierVolatile = 4,
+ QualifierReference = 8,
+ QualifierRValueReference = 16,
+ QualifierPointer = 32
+};
+
+/// @brief Categorizes the recognized operators
+
+enum class OperatorKind
+{
+ Unary,
+ Postfix,
+ Binary,
+ Ternary,
+ Other,
+ ConversionOperator,
+ Vendor,
+ NoMatch
+};
+
+/// @brief Represents one of the recognized two-character operator
+/// abbreviations used when parsing operators as names and expressions
+
+struct Operator
+{
+ const char * name;
+ OperatorKind kind;
+};
+
+/// @brief Represents a range of characters in the output buffer, typically for
+/// use with RewriteRange()
+
+struct BufferRange
+{
+ int offset;
+ int length;
+};
+
+/// @brief Transient state required while parsing a name
+
+struct NameState
+{
+ bool parse_function_params;
+ bool is_last_generic;
+ bool has_no_return_type;
+ BufferRange last_name_range;
+};
+
+/// @brief LLDB's fast C++ demangler
+///
+/// This is an incomplete implementation designed to speed up the demangling
+/// process that is often a bottleneck when LLDB stops a process for the first
+/// time. Where the implementation doesn't know how to demangle a symbol it
+/// fails gracefully to allow the caller to fall back to the existing demangler.
+///
+/// Over time the full mangling spec should be supported without compromising
+/// performance for the most common cases.
+
+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;
+ }
+
+ /// @brief Create a SymbolDemangler that uses provided scratch memory
+ ///
+ /// The provided memory is not owned by the demangler. It will be
+ /// overwritten during calls to GetDemangledCopy() but can be used for
+ /// other purposes between calls. The provided memory will not be freed
+ /// when this instance is destroyed.
+ ///
+ /// If demangling a symbol requires additional space it will be allocated
+ /// and managed by the demangler instance.
+ ///
+ /// @param storage_ptr Valid pointer to at least storage_size bytes of
+ /// space that the SymbolDemangler can use during demangling
+ ///
+ /// @param storage_size Number of bytes of space available scratch memory
+ /// referenced by storage_ptr
+
+ 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;
+
+ // 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;
+ }
+
+ /// @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);
+ }
+
+#ifdef DEBUG_HIGHWATER
+ int highwater_store = 0;
+ int highwater_buffer = 0;
+#endif
+
+ /// @brief Parses the provided mangled name and returns a newly allocated
+ /// demangling
+ ///
+ /// @param mangled_name Valid null-terminated C++ mangled name following
+ /// the Itanium C++ ABI mangling specification as implemented by Clang
+ ///
+ /// @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)
+ {
+ 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;
+#endif
+
+ int length = (int)(write_ptr - buffer);
+ char * copy = (char *)malloc(length + 1);
+ memcpy(copy, 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;
+
+ // Avoid growing by more than 1MB at a time
+ 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;
+
+ // Update references to the new buffer
+ write_ptr = new_buffer + (write_ptr - buffer);
+ buffer = new_buffer;
+ buffer_end = buffer + new_size;
+ }
+
+ void GrowRewriteRanges()
+ {
+ // By default, double the size of the array
+ int growth = rewrite_ranges_size;
+
+ // Apply reasonable minimum and maximum sizes for growth
+ 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++)
+ {
+ new_ranges[index] = rewrite_ranges[index];
+ }
+ for (int index = rewrite_ranges_size - 1;
+ index > next_template_arg_index; index--)
+ {
+ new_ranges[index + growth] = rewrite_ranges[index];
+ }
+ if (owns_rewrite_ranges) free(rewrite_ranges);
+ owns_rewrite_ranges = true;
+
+ // Update references to the new array
+ rewrite_ranges = new_ranges;
+ rewrite_ranges_size += growth;
+ next_template_arg_index += growth;
+ }
+
+ //----------------------------------------------------
+ // Range and state management
+ //----------------------------------------------------
+
+ int GetStartCookie()
+ {
+ return (int)(write_ptr - buffer);
+ }
+
+ BufferRange EndRange(int start_cookie)
+ {
+ return { start_cookie, (int)(write_ptr - (buffer + start_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)
+ {
+ GrowBuffer(write_ptr + source_range.length - 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,
+ source_range.offset - insertion_point_cookie);
+ memcpy(buffer + insertion_point_cookie, 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;
+
+ // 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;
+ if (candidate_offset >= insertion_point_cookie)
+ {
+ if (candidate_offset < source_range.offset)
+ {
+ rewrite_ranges[index].offset += source_range.length;
+ }
+ else if (candidate_offset >= source_range.offset)
+ {
+ rewrite_ranges[index].offset -=
+ (source_range.offset - insertion_point_cookie);
+ }
+ }
+ ++index;
+ }
+ }
+
+ 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);
+#ifdef DEBUG_SUBSTITUTIONS
+ printf("Saved substitution # %d = %.*s\n", index,
+ rewrite_ranges[index].length, buffer + start_cookie);
+#endif
+ }
+
+ 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);
+#ifdef DEBUG_TEMPLATE_ARGS
+ printf("Saved template arg # %d = %.*s\n",
+ rewrite_ranges_size - index - 1,
+ rewrite_ranges[index].length, buffer + start_cookie);
+#endif
+ }
+
+ 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;
+ }
+
+ //----------------------------------------------------
+ // Write methods
+ //
+ // Appends content to the existing output buffer
+ //----------------------------------------------------
+
+ void Write(char character)
+ {
+ if (write_ptr == buffer_end) GrowBuffer();
+ *write_ptr++ = character;
+ }
+
+ void Write(const char * content)
+ {
+ Write(content, strlen(content));
+ }
+
+ void Write(const char * content, long content_length)
+ {
+ char * end_write_ptr = write_ptr + content_length;
+ if (end_write_ptr > buffer_end)
+ {
+ GrowBuffer(end_write_ptr - buffer_end);
+ end_write_ptr = write_ptr + content_length;
+ }
+ memcpy(write_ptr, content, content_length);
+ write_ptr = end_write_ptr;
+ }
+#define WRITE(x) Write(x, sizeof(x) - 1)
+
+ void WriteTemplateStart()
+ {
+ Write('<');
+ }
+
+ void WriteTemplateEnd()
+ {
+ // Put a space between terminal > characters when nesting templates
+ if (write_ptr != buffer && *(write_ptr - 1) == '>') WRITE(" >");
+ else Write('>');
+ }
+
+ void WriteCommaSpace()
+ {
+ WRITE(", ");
+ }
+
+ void WriteNamespaceSeparator()
+ {
+ WRITE("::");
+ }
+
+ 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");
+ if (qualifiers & QualifierReference)
+ {
+ if (space_before_reference) WRITE(" &");
+ else Write('&');
+ }
+ if (qualifiers & QualifierRValueReference)
+ {
+ 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)
+ {
+ Write(buffer + range.offset, range.length);
+ }
+
+ bool RewriteSubstitution(int index)
+ {
+ if (index < 0 || index >= next_substitute_index)
+ {
+#ifdef DEBUG_FAILURES
+ printf("*** Invalid substitution #%d\n", index);
+#endif
+ return false;
+ }
+ RewriteRange(rewrite_ranges[index]);
+ return true;
+ }
+
+ bool RewriteTemplateArg(int template_index)
+ {
+ int index = rewrite_ranges_size - 1 - template_index;
+ if (template_index < 0 || index <= next_template_arg_index)
+ {
+#ifdef DEBUG_FAILURES
+ printf("*** Invalid template arg reference #%d\n", template_index);
+#endif
+ return false;
+ }
+ RewriteRange(rewrite_ranges[index]);
+ return true;
+ }
+
+ //----------------------------------------------------
+ // TryParse methods
+ //
+ // Provide information with return values instead of
+ // writing to the output buffer
+ //
+ // Values indicating failure guarantee that the pre-
+ // call read_ptr is unchanged
+ //----------------------------------------------------
+
+ int TryParseNumber()
+ {
+ unsigned char digit = *read_ptr - '0';
+ if (digit > 9) return -1;
+
+ int count = digit;
+ while (true)
+ {
+ digit = *++read_ptr - '0';
+ if (digit > 9) break;
+
+ count = count * 10 + digit;
+ }
+ return count;
+ }
+
+ int TryParseBase36Number()
+ {
+ char digit = *read_ptr;
+ int count;
+ 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);
+ else break;
+
+ count = count * 36 + digit;
+ }
+ return count;
+ }
+
+ // <builtin-type> ::= v # void
+ // ::= w # wchar_t
+ // ::= b # bool
+ // ::= c # char
+ // ::= a # signed char
+ // ::= h # unsigned char
+ // ::= s # short
+ // ::= t # unsigned short
+ // ::= i # int
+ // ::= j # unsigned int
+ // ::= l # long
+ // ::= m # unsigned long
+ // ::= x # long long, __int64
+ // ::= y # unsigned long long, __int64
+ // ::= n # __int128
+ // ::= o # unsigned __int128
+ // ::= f # float
+ // ::= d # double
+ // ::= e # long double, __float80
+ // ::= g # __float128
+ // ::= z # ellipsis
+ // ::= Dd # IEEE 754r decimal floating point (64 bits)
+ // ::= De # IEEE 754r decimal floating point (128 bits)
+ // ::= Df # IEEE 754r decimal floating point (32 bits)
+ // ::= Dh # IEEE 754r half-precision floating point (16 bits)
+ // ::= Di # char32_t
+ // ::= Ds # char16_t
+ // ::= Da # auto (in dependent new-expressions)
+ // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
+ // ::= u <source-name> # vendor extended type
+
+ const char * TryParseBuiltinType()
+ {
+ switch (*read_ptr++)
+ {
+ case 'v': return "void";
+ case 'w': return "wchar_t";
+ case 'b': return "bool";
+ case 'c': return "char";
+ case 'a': return "signed char";
+ case 'h': return "unsigned char";
+ case 's': return "short";
+ case 't': return "unsigned short";
+ case 'i': return "int";
+ case 'j': return "unsigned int";
+ case 'l': return "long";
+ case 'm': return "unsigned long";
+ case 'x': return "long long";
+ case 'y': return "unsigned long long";
+ case 'n': return "__int128";
+ case 'o': return "unsigned __int128";
+ case 'f': return "float";
+ case 'd': return "double";
+ case 'e': return "long double";
+ case 'g': return "__float128";
+ case 'z': return "...";
+ case 'D':
+ {
+ switch (*read_ptr++)
+ {
+ case 'd': return "decimal64";
+ case 'e': return "decimal128";
+ case 'f': return "decimal32";
+ case 'h': return "decimal16";
+ case 'i': return "char32_t";
+ case 's': return "char16_t";
+ case 'a': return "auto";
+ case 'c': return "decltype(auto)";
+ case 'n': return "std::nullptr_t";
+ default:
+ --read_ptr;
+ }
+ }
+ }
+ --read_ptr;
+ return nullptr;
+ }
+
+ // <operator-name>
+ // ::= aa # &&
+ // ::= ad # & (unary)
+ // ::= an # &
+ // ::= aN # &=
+ // ::= aS # =
+ // ::= cl # ()
+ // ::= cm # ,
+ // ::= co # ~
+ // ::= da # delete[]
+ // ::= de # * (unary)
+ // ::= dl # delete
+ // ::= dv # /
+ // ::= dV # /=
+ // ::= eo # ^
+ // ::= eO # ^=
+ // ::= eq # ==
+ // ::= ge # >=
+ // ::= gt # >
+ // ::= ix # []
+ // ::= le # <=
+ // ::= ls # <<
+ // ::= lS # <<=
+ // ::= lt # <
+ // ::= mi # -
+ // ::= mI # -=
+ // ::= ml # *
+ // ::= mL # *=
+ // ::= mm # -- (postfix in <expression> context)
+ // ::= na # new[]
+ // ::= ne # !=
+ // ::= ng # - (unary)
+ // ::= nt # !
+ // ::= nw # new
+ // ::= oo # ||
+ // ::= or # |
+ // ::= oR # |=
+ // ::= pm # ->*
+ // ::= pl # +
+ // ::= pL # +=
+ // ::= pp # ++ (postfix in <expression> context)
+ // ::= ps # + (unary)
+ // ::= pt # ->
+ // ::= qu # ?
+ // ::= rm # %
+ // ::= rM # %=
+ // ::= rs # >>
+ // ::= rS # >>=
+ // ::= cv <type> # (cast)
+ // ::= v <digit> <source-name> # vendor extended operator
+
+ Operator TryParseOperator()
+ {
+ switch (*read_ptr++)
+ {
+ case 'a':
+ switch (*read_ptr++)
+ {
+ case 'a': return { "&&", OperatorKind::Binary };
+ case 'd': return { "&", OperatorKind::Unary };
+ case 'n': return { "&", OperatorKind::Binary };
+ case 'N': return { "&=", OperatorKind::Binary };
+ case 'S': return { "=", OperatorKind::Binary };
+ }
+ --read_ptr;
+ break;
+ case 'c':
+ switch (*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;
+ break;
+ case 'd':
+ switch (*read_ptr++)
+ {
+ case 'a': return { " delete[]", OperatorKind::Other };
+ case 'e': return { "*", OperatorKind::Unary };
+ case 'l': return { " delete", OperatorKind::Other };
+ case 'v': return { "/", OperatorKind::Binary };
+ case 'V': return { "/=", OperatorKind::Binary };
+ }
+ --read_ptr;
+ break;
+ case 'e':
+ switch (*read_ptr++)
+ {
+ case 'o': return { "^", OperatorKind::Binary };
+ case 'O': return { "^=", OperatorKind::Binary };
+ case 'q': return { "==", OperatorKind::Binary };
+ }
+ --read_ptr;
+ break;
+ case 'g':
+ switch (*read_ptr++)
+ {
+ case 'e': return { ">=", OperatorKind::Binary };
+ case 't': return { ">", OperatorKind::Binary };
+ }
+ --read_ptr;
+ break;
+ case 'i':
+ switch (*read_ptr++)
+ {
+ case 'x': return { "[]", OperatorKind::Other };
+ }
+ --read_ptr;
+ break;
+ case 'l':
+ switch (*read_ptr++)
+ {
+ case 'e': return { "<=", OperatorKind::Binary };
+ case 's': return { "<<", OperatorKind::Binary };
+ case 'S': return { "<<=", OperatorKind::Binary };
+ case 't': return { "<", OperatorKind::Binary };
+ // case 'i': return { "?", OperatorKind::Binary };
+ }
+ --read_ptr;
+ break;
+ case 'm':
+ switch (*read_ptr++)
+ {
+ case 'i': return { "-", OperatorKind::Binary };
+ case 'I': return { "-=", OperatorKind::Binary };
+ case 'l': return { "*", OperatorKind::Binary };
+ case 'L': return { "*=", OperatorKind::Binary };
+ case 'm': return { "--", OperatorKind::Postfix };
+ }
+ --read_ptr;
+ break;
+ case 'n':
+ switch (*read_ptr++)
+ {
+ case 'a': return { " new[]", OperatorKind::Other };
+ case 'e': return { "!=", OperatorKind::Binary };
+ case 'g': return { "-", OperatorKind::Unary };
+ case 't': return { "!", OperatorKind::Unary };
+ case 'w': return { " new", OperatorKind::Other };
+ }
+ --read_ptr;
+ break;
+ case 'o':
+ switch (*read_ptr++)
+ {
+ case 'o': return { "||", OperatorKind::Binary };
+ case 'r': return { "|", OperatorKind::Binary };
+ case 'R': return { "|=", OperatorKind::Binary };
+ }
+ --read_ptr;
+ break;
+ case 'p':
+ switch (*read_ptr++)
+ {
+ case 'm': return { "->*", OperatorKind::Binary };
+ case 's': return { "+", OperatorKind::Unary };
+ case 'l': return { "+", OperatorKind::Binary };
+ case 'L': return { "+=", OperatorKind::Binary };
+ case 'p': return { "++", OperatorKind::Postfix };
+ case 't': return { "->", OperatorKind::Binary };
+ }
+ --read_ptr;
+ break;
+ case 'q':
+ switch (*read_ptr++)
+ {
+ case 'u': return { "?", OperatorKind::Ternary };
+ }
+ --read_ptr;
+ break;
+ case 'r':
+ switch (*read_ptr++)
+ {
+ case 'm': return { "%", OperatorKind::Binary };
+ case 'M': return { "%=", OperatorKind::Binary };
+ case 's': return { ">>", OperatorKind::Binary };
+ case 'S': return { ">=", OperatorKind::Binary };
+ }
+ --read_ptr;
+ break;
+ case 'v':
+ char digit = *read_ptr;
+ if (digit >= '0' && digit <= '9')
+ {
+ read_ptr++;
+ return { nullptr, OperatorKind::Vendor };
+ }
+ --read_ptr;
+ break;
+ }
+ --read_ptr;
+ return { nullptr, OperatorKind::NoMatch };
+ }
+
+ // <CV-qualifiers> ::= [r] [V] [K]
+ // <ref-qualifier> ::= R # & ref-qualifier
+ // <ref-qualifier> ::= O # && ref-qualifier
+
+ int TryParseQualifiers(bool allow_cv, bool allow_ro)
+ {
+ int qualifiers = QualifierNone;
+ char next = *read_ptr;
+ if (allow_cv)
+ {
+ if (next == 'r') // restrict
+ {
+ qualifiers |= QualifierRestrict;
+ next = *++read_ptr;
+ }
+ if (next == 'V') // volatile
+ {
+ qualifiers |= QualifierVolatile;
+ next = *++read_ptr;
+ }
+ if (next == 'K') // const
+ {
+ qualifiers |= QualifierConst;
+ next = *++read_ptr;
+ }
+ }
+ if (allow_ro)
+ {
+ if (next == 'R')
+ {
+ ++read_ptr;
+ qualifiers |= QualifierReference;
+ }
+ else if (next =='O')
+ {
+ ++read_ptr;
+ qualifiers |= QualifierRValueReference;
+ }
+ }
+ return qualifiers;
+ }
+
+ // <discriminator> := _ <non-negative number> # when number < 10
+ // := __ <non-negative number> _ # when number >= 10
+ // extension := decimal-digit+
+
+ int TryParseDiscriminator()
+ {
+ const char * discriminator_start = 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 (next == '_')
+ {
+ next = *++read_ptr;
+ if (next == '_')
+ {
+ ++read_ptr;
+ discriminator_value = TryParseNumber();
+ if (discriminator_value != -1 && *read_ptr++ != '_')
+ {
+ return discriminator_value;
+ }
+ }
+ else if (next >= '0' && next <= '9')
+ {
+ ++read_ptr;
+ return next - '0';
+ }
+ }
+
+ // Not a valid discriminator
+ read_ptr = discriminator_start;
+ return -1;
+ }
+
+ //----------------------------------------------------
+ // Parse methods
+ //
+ // Consume input starting from read_ptr and produce
+ // buffered output at write_ptr
+ //
+ // Failures return false and may leave read_ptr in an
+ // indeterminate state
+ //----------------------------------------------------
+
+ bool Parse(char character)
+ {
+ if (*read_ptr++ == character) return true;
+#ifdef DEBUG_FAILURES
+ printf("*** Expected '%c'\n", character);
+#endif
+ return false;
+ }
+
+ // <number> ::= [n] <non-negative decimal integer>
+
+ bool ParseNumber(bool allow_negative = false)
+ {
+ if (allow_negative && *read_ptr == 'n')
+ {
+ Write('-');
+ ++read_ptr;
+ }
+ const char * before_digits = read_ptr;
+ while (true)
+ {
+ unsigned char digit = *read_ptr - '0';
+ if (digit > 9) break;
+ ++read_ptr;
+ }
+ if (int digit_count = (int)(read_ptr - before_digits))
+ {
+ Write(before_digits, digit_count);
+ return true;
+ }
+#ifdef DEBUG_FAILURES
+ printf("*** Expected number\n");
+#endif
+ return false;
+ }
+
+ // <substitution> ::= S <seq-id> _
+ // ::= S_
+ // <substitution> ::= Sa # ::std::allocator
+ // <substitution> ::= Sb # ::std::basic_string
+ // <substitution> ::= Ss # ::std::basic_string < char,
+ // ::std::char_traits<char>,
+ // ::std::allocator<char> >
+ // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
+ // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
+ // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
+
+ bool ParseSubstitution()
+ {
+ const char * substitution;
+ switch (*read_ptr)
+ {
+ case 'a': substitution = "std::allocator"; break;
+ case 'b': substitution = "std::basic_string"; break;
+ case 's': substitution = "std::string"; break;
+ case 'i': substitution = "std::istream"; break;
+ case 'o': substitution = "std::ostream"; break;
+ case 'd': substitution = "std::iostream"; break;
+ default:
+ // 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++ != '_')
+ {
+#ifdef DEBUG_FAILURES
+ printf("*** Expected terminal _ in substitution\n");
+#endif
+ return false;
+ }
+ return RewriteSubstitution(substitution_index + 1);
+ }
+ Write(substitution);
+ ++read_ptr;
+ return true;
+ }
+
+ // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
+ //
+ // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
+
+ bool ParseFunctionType(int inner_qualifiers = QualifierNone)
+ {
+#ifdef DEBUG_FAILURES
+ printf("*** Function types not supported\n");
+#endif
+ //TODO: first steps toward an implementation follow, but they're far
+ // from complete. Function types tend to bracket other types eg:
+ // 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;;
+
+ int return_type_start_cookie = GetStartCookie();
+ if (!ParseType()) return false;
+ Write(' ');
+
+ int insert_cookie = GetStartCookie();
+ Write('(');
+ bool first_param = true;
+ int qualifiers = QualifierNone;
+ while (true)
+ {
+ switch (*read_ptr)
+ {
+ case 'E':
+ ++read_ptr;
+ Write(')');
+ break;
+ case 'v':
+ ++read_ptr;
+ continue;
+ case 'R':
+ case 'O':
+ if (*(read_ptr + 1) == 'E')
+ {
+ qualifiers = TryParseQualifiers(false, true);
+ Parse('E');
+ break;
+ }
+ // fallthrough
+ default:
+ {
+ if (first_param) first_param = false;
+ else WriteCommaSpace();
+
+ if (!ParseType()) return false;
+ continue;
+ }
+ }
+ break;
+ }
+
+ if (qualifiers)
+ {
+ 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);
+ }
+ return true;
+ }
+
+ // <array-type> ::= A <positive dimension number> _ <element type>
+ // ::= A [<dimension expression>] _ <element type>
+
+ bool ParseArrayType(int qualifiers = QualifierNone)
+ {
+#ifdef DEBUG_FAILURES
+ printf("*** Array type unsupported\n");
+#endif
+ //TODO: We fail horribly when recalling these as substitutions or
+ // templates and trying to constify them eg:
+ // _ZN4llvm2cl5applyIA28_cNS0_3optIbLb0ENS0_6parserIbEEEEEEvRKT_PT0_
+ //
+ //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 == '_')
+ {
+ ++read_ptr;
+ if (!ParseType()) return false;
+ if (qualifiers) WriteQualifiers(qualifiers);
+ WRITE(" []");
+ return true;
+ }
+ else
+ {
+ const char * before_digits = read_ptr;
+ if (TryParseNumber() != -1)
+ {
+ const char * after_digits = read_ptr;
+ if (!Parse('_')) return false;
+ if (!ParseType()) return false;
+ if (qualifiers) WriteQualifiers(qualifiers);
+ Write(' ');
+ Write('[');
+ Write(before_digits, after_digits - before_digits);
+ }
+ else
+ {
+ int type_insertion_cookie = GetStartCookie();
+ if (!ParseExpression()) return false;
+ if (!Parse('_')) return false;
+
+ int type_start_cookie = GetStartCookie();
+ if (!ParseType()) return false;
+ if (qualifiers) WriteQualifiers(qualifiers);
+ Write(' ');
+ Write('[');
+ ReorderRange(EndRange(type_start_cookie), type_insertion_cookie);
+ }
+ Write(']');
+ return true;
+ }
+ }
+
+ // <pointer-to-member-type> ::= M <class type> <member type>
+
+ //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()
+ {
+ int insertion_cookie = GetStartCookie();
+ Write(' ');
+ if (!ParseType()) return false;
+ WRITE("::*");
+
+ int type_cookie = GetStartCookie();
+ if (!ParseType()) return false;
+ ReorderRange(EndRange(type_cookie), insertion_cookie);
+ return true;
+ }
+
+ // <template-param> ::= T_ # first template parameter
+ // ::= T <parameter-2 non-negative number> _
+
+ bool ParseTemplateParam()
+ {
+ int count = TryParseNumber();
+ 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);
+ }
+
+ // <type> ::= <builtin-type>
+ // ::= <function-type>
+ // ::= <class-enum-type>
+ // ::= <array-type>
+ // ::= <pointer-to-member-type>
+ // ::= <template-param>
+ // ::= <template-template-param> <template-args>
+ // ::= <decltype>
+ // ::= <substitution>
+ // ::= <CV-qualifiers> <type>
+ // ::= P <type> # pointer-to
+ // ::= R <type> # reference-to
+ // ::= O <type> # rvalue reference-to (C++0x)
+ // ::= C <type> # complex pair (C 2000)
+ // ::= G <type> # imaginary (C 2000)
+ // ::= Dp <type> # pack expansion (C++0x)
+ // ::= U <source-name> <type> # vendor extended type qualifier
+ // extension := U <objc-name> <objc-type> # objc-type<identifier>
+ // extension := <vector-type> # <vector-type> starts with Dv
+
+ // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
+ // <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
+
+ bool ParseType()
+ {
+#ifdef DEBUG_FAILURES
+ const char * failed_type = read_ptr;
+#endif
+ int type_start_cookie = GetStartCookie();
+ bool suppress_substitution = false;
+
+ int qualifiers = TryParseQualifiers(true, false);
+ switch (*read_ptr)
+ {
+ case 'D':
+ ++read_ptr;
+ switch (*read_ptr++)
+ {
+ case 'p':
+ if (!ParseType()) return false;
+ break;
+ case 'T':
+ case 't':
+ case 'v':
+ default:
+#ifdef DEBUG_FAILURES
+ printf("*** Unsupported type: %.3s\n", failed_type);
+#endif
+ return false;
+ }
+ break;
+ case 'T':
+ ++read_ptr;
+ if (!ParseTemplateParam()) return false;
+ break;
+ case 'M':
+ ++read_ptr;
+ if (!ParsePointerToMemberType()) return false;
+ break;
+ case 'A':
+ ++read_ptr;
+ if (!ParseArrayType()) return false;
+ break;
+ case 'F':
+ ++read_ptr;
+ if (!ParseFunctionType()) return false;
+ break;
+ case 'S':
+ if (*++read_ptr == 't')
+ {
+ ++read_ptr;
+ WriteStdPrefix();
+ if (!ParseName()) return false;
+ }
+ else
+ {
+ suppress_substitution = true;
+ if (!ParseSubstitution()) return false;
+ }
+ break;
+ case 'P':
+ {
+ switch (*++read_ptr)
+ {
+ case 'F':
+ ++read_ptr;
+ if (!ParseFunctionType(QualifierPointer)) return false;
+ break;
+ default:
+ if (!ParseType()) return false;
+ Write('*');
+ break;
+ }
+ break;
+ }
+ case 'R':
+ {
+ ++read_ptr;
+ if (!ParseType()) return false;
+ Write('&');
+ break;
+ }
+ case 'O':
+ {
+ ++read_ptr;
+ if (!ParseType()) return false;
+ Write('&');
+ Write('&');
+ break;
+ }
+ case 'C':
+ case 'G':
+ case 'U':
+#ifdef DEBUG_FAILURES
+ printf("*** Unsupported type: %.3s\n", failed_type);
+#endif
+ return false;
+ // Test for common cases to avoid TryParseBuiltinType() overhead
+ case 'N':
+ case 'Z':
+ case 'L':
+ if (!ParseName()) return false;
+ break;
+ default:
+ if (const char * builtin = TryParseBuiltinType())
+ {
+ Write(builtin);
+ suppress_substitution = true;
+ }
+ else
+ {
+ 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 (qualifiers)
+ {
+ WriteQualifiers(qualifiers, false);
+ EndSubstitution(type_start_cookie);
+ }
+ return true;
+ }
+
+ // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
+ // ::= <closure-type-name>
+ //
+ // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
+ //
+ // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
+
+ bool ParseUnnamedTypeName(NameState & name_state)
+ {
+ switch (*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;
+ Write('\'');
+ 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;
+ Write('\'');
+ name_state.last_name_range = EndRange(cookie);
+ return true;
+ }
+ case 'l':
+#ifdef DEBUG_FAILURES
+ printf("*** Lambda type names unsupported\n");
+#endif
+ return false;
+ }
+#ifdef DEBUG_FAILURES
+ printf("*** Unknown unnamed type %.3s\n", read_ptr - 2);
+#endif
+ return false;
+ }
+
+ // <ctor-dtor-name> ::= C1 # complete object constructor
+ // ::= C2 # base object constructor
+ // ::= C3 # complete object allocating constructor
+
+ bool ParseCtor(NameState & name_state)
+ {
+ char next = *read_ptr;
+ if (next == '1' || next == '2' || next == '3' || next == '5')
+ {
+ RewriteRange(name_state.last_name_range);
+ name_state.has_no_return_type = true;
+ ++read_ptr;
+ return true;
+ }
+#ifdef DEBUG_FAILURES
+ printf("*** Broken constructor\n");
+#endif
+ return false;
+ }
+
+ // <ctor-dtor-name> ::= D0 # deleting destructor
+ // ::= D1 # complete object destructor
+ // ::= D2 # base object destructor
+
+ bool ParseDtor(NameState & name_state)
+ {
+ char next = *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;
+ return true;
+ }
+#ifdef DEBUG_FAILURES
+ printf("*** Broken destructor\n");
+#endif
+ return false;
+ }
+
+ // See TryParseOperator()
+
+ bool ParseOperatorName(NameState & name_state)
+ {
+#ifdef DEBUG_FAILURES
+ const char * operator_ptr = read_ptr;
+#endif
+ Operator parsed_operator = TryParseOperator();
+ if (parsed_operator.name)
+ {
+ WRITE("operator");
+ Write(parsed_operator.name);
+ return true;
+ }
+
+ // Handle special operators
+ switch (parsed_operator.kind)
+ {
+ case OperatorKind::Vendor:
+ WRITE("operator ");
+ return ParseSourceName();
+ case OperatorKind::ConversionOperator:
+ ResetTemplateArgs();
+ name_state.has_no_return_type = true;
+ WRITE("operator ");
+ return ParseType();
+ default:
+#ifdef DEBUG_FAILURES
+ printf("*** Unknown operator: %.2s\n", operator_ptr);
+#endif
+ return false;
+ }
+ }
+
+ // <source-name> ::= <positive length number> <identifier>
+
+ bool ParseSourceName()
+ {
+ int count = TryParseNumber();
+ if (count == -1)
+ {
+#ifdef DEBUG_FAILURES
+ printf("*** Malformed source name, missing length count\n");
+#endif
+ return false;
+ }
+
+ const char * next_read_ptr = read_ptr + count;
+ if (next_read_ptr > 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;
+ return true;
+ }
+
+ // <unqualified-name> ::= <operator-name>
+ // ::= <ctor-dtor-name>
+ // ::= <source-name>
+ // ::= <unnamed-type-name>
+
+ 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;
+ switch (next)
+ {
+ case 'C':
+ ++read_ptr;
+ return ParseCtor(name_state);
+ case 'D':
+ ++read_ptr;
+ return ParseDtor(name_state);
+ case 'U':
+ ++read_ptr;
+ return ParseUnnamedTypeName(name_state);
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ int name_start_cookie = GetStartCookie();
+ if (!ParseSourceName()) return false;
+ name_state.last_name_range = EndRange(name_start_cookie);
+ return true;
+ }
+ default:
+ return ParseOperatorName(name_state);
+ };
+ }
+
+ // <unscoped-name> ::= <unqualified-name>
+ // ::= St <unqualified-name> # ::std::
+ // extension ::= StL<unqualified-name>
+
+ bool ParseUnscopedName(NameState & name_state)
+ {
+ if (*read_ptr == 'S' && *(read_ptr + 1) == 't')
+ {
+ WriteStdPrefix();
+ if (*(read_ptr += 2) == 'L') ++read_ptr;
+ }
+ return ParseUnqualifiedName(name_state);
+ }
+
+ 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);
+ return Parse('E');
+ }
+
+ bool ParseBooleanLiteral()
+ {
+ switch (*read_ptr++)
+ {
+ case '0': WRITE("false"); break;
+ case '1': WRITE("true"); break;
+ default:
+#ifdef DEBUG_FAILURES
+ printf("*** Boolean literal not 0 or 1\n");
+#endif
+ return false;
+ }
+ return Parse('E');
+ }
+
+ // <expr-primary> ::= L <type> <value number> E # integer literal
+ // ::= L <type> <value float> E # floating literal
+ // ::= L <string type> E # string literal
+ // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
+ // ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
+ // ::= L <mangled-name> E # external name
+
+ bool ParseExpressionPrimary()
+ {
+ switch (*read_ptr++)
+ {
+ case 'b': return ParseBooleanLiteral();
+ case 'x': return ParseIntegerLiteral(nullptr, "ll", true);
+ case 'l': return ParseIntegerLiteral(nullptr, "l", true);
+ case 'i': return ParseIntegerLiteral(nullptr, nullptr, true);
+ case 'n': return ParseIntegerLiteral("(__int128)", nullptr, true);
+ case 'j': return ParseIntegerLiteral(nullptr, "u", false);
+ case 'm': return ParseIntegerLiteral(nullptr, "ul", false);
+ case 'y': return ParseIntegerLiteral(nullptr, "ull", false);
+ case 'o': return ParseIntegerLiteral("(unsigned __int128)",
+ nullptr, false);
+ case '_':
+ if (*read_ptr++ == 'Z')
+ {
+ if (!ParseEncoding()) return false;
+ return Parse('E');
+ }
+ --read_ptr;
+ // fallthrough
+ case 'w':
+ case 'c':
+ case 'a':
+ case 'h':
+ case 's':
+ case 't':
+ case 'f':
+ case 'd':
+ case 'e':
+#ifdef DEBUG_FAILURES
+ printf("*** Unsupported primary expression %.5s\n", read_ptr - 1);
+#endif
+ return false;
+ case 'T':
+ // Invalid mangled name per
+ // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
+#ifdef DEBUG_FAILURES
+ printf("*** Invalid primary expr encoding\n");
+#endif
+ return false;
+ default:
+ --read_ptr;
+ Write('(');
+ if (!ParseType()) return false;
+ Write(')');
+ if (!ParseNumber()) return false;
+ return Parse('E');
+ }
+ }
+
+ // <unresolved-type> ::= <template-param>
+ // ::= <decltype>
+ // ::= <substitution>
+
+ bool ParseUnresolvedType()
+ {
+ int type_start_cookie = GetStartCookie();
+ switch (*read_ptr++)
+ {
+ case 'T':
+ if (!ParseTemplateParam()) return false;
+ EndSubstitution(type_start_cookie);
+ return true;
+ case 'S':
+ {
+ if (*read_ptr != 't') return ParseSubstitution();
+
+ ++read_ptr;
+ WriteStdPrefix();
+ NameState type_name = {};
+ 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);
+#endif
+ return false;
+ }
+ }
+
+ // <base-unresolved-name> ::= <simple-id> # unresolved name
+ // extension ::= <operator-name> # unresolved operator-function-id
+ // extension ::= <operator-name> <template-args> # unresolved operator template-id
+ // ::= on <operator-name> # unresolved operator-function-id
+ // ::= on <operator-name> <template-args> # unresolved operator template-id
+ // ::= dn <destructor-name> # destructor or pseudo-destructor;
+ // # e.g. ~X or ~X<N-1>
+
+ bool ParseBaseUnresolvedName()
+ {
+#ifdef DEBUG_FAILURES
+ printf("*** Base unresolved name unsupported\n");
+#endif
+ return false;
+ }
+
+ // <unresolved-name>
+ // extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
+ // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
+ // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
+ // # A::x, N::y, A<T>::z; "gs" means leading "::"
+ // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
+ // extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
+ // # T::N::x /decltype(p)::N::x
+ // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
+
+ 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')
+ {
+ read_ptr += 2;
+ WriteNamespaceSeparator();
+ }
+ }
+
+ // <expression> ::= <unary operator-name> <expression>
+ // ::= <binary operator-name> <expression> <expression>
+ // ::= <ternary operator-name> <expression> <expression> <expression>
+ // ::= cl <expression>+ E # call
+ // ::= cv <type> <expression> # conversion with one argument
+ // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
+ // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
+ // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
+ // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
+ // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
+ // ::= [gs] dl <expression> # delete expression
+ // ::= [gs] da <expression> # delete[] expression
+ // ::= pp_ <expression> # prefix ++
+ // ::= mm_ <expression> # prefix --
+ // ::= ti <type> # typeid (type)
+ // ::= te <expression> # typeid (expression)
+ // ::= dc <type> <expression> # dynamic_cast<type> (expression)
+ // ::= sc <type> <expression> # static_cast<type> (expression)
+ // ::= cc <type> <expression> # const_cast<type> (expression)
+ // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
+ // ::= st <type> # sizeof (a type)
+ // ::= sz <expression> # sizeof (an expression)
+ // ::= at <type> # alignof (a type)
+ // ::= az <expression> # alignof (an expression)
+ // ::= nx <expression> # noexcept (expression)
+ // ::= <template-param>
+ // ::= <function-param>
+ // ::= dt <expression> <unresolved-name> # expr.name
+ // ::= pt <expression> <unresolved-name> # expr->name
+ // ::= ds <expression> <expression> # expr.*expr
+ // ::= sZ <template-param> # size of a parameter pack
+ // ::= sZ <function-param> # size of a function parameter pack
+ // ::= sp <expression> # pack expansion
+ // ::= tw <expression> # throw expression
+ // ::= tr # throw with no operand (rethrow)
+ // ::= <unresolved-name> # f(p), N::f(p), ::f(p),
+ // # freestanding dependent name (e.g., T::x),
+ // # objectless nonstatic member reference
+ // ::= <expr-primary>
+
+ bool ParseExpression()
+ {
+ Operator expression_operator = TryParseOperator();
+ switch (expression_operator.kind)
+ {
+ case OperatorKind::Unary:
+ Write(expression_operator.name);
+ Write('(');
+ if (!ParseExpression()) return false;
+ Write(')');
+ return true;
+ case OperatorKind::Binary:
+ if (!ParseExpression()) return false;
+ Write(expression_operator.name);
+ return ParseExpression();
+ case OperatorKind::Ternary:
+ if (!ParseExpression()) return false;
+ Write('?');
+ if (!ParseExpression()) return false;
+ Write(':');
+ return ParseExpression();
+ case OperatorKind::NoMatch:
+ break;
+ case OperatorKind::Other:
+ default:
+#ifdef DEBUG_FAILURES
+ printf("*** Unsupported operator: %s\n", expression_operator.name);
+#endif
+ return false;
+ }
+
+ switch (*read_ptr++)
+ {
+ case 'T': return ParseTemplateParam();
+ case 'L': return ParseExpressionPrimary();
+ case 's':
+ if (*read_ptr++ == 'r') return ParseUnresolvedName();
+ --read_ptr;
+ // fallthrough
+ default:
+ return ParseExpressionPrimary();
+ }
+ }
+
+ // <template-arg> ::= <type> # type or template
+ // ::= X <expression> E # expression
+ // ::= <expr-primary> # simple expressions
+ // ::= J <template-arg>* E # argument pack
+ // ::= LZ <encoding> E # extension
+
+ bool ParseTemplateArg()
+ {
+ switch (*read_ptr) {
+ case 'J':
+#ifdef DEBUG_FAILURES
+ printf("*** Template argument packs unsupported\n");
+#endif
+ return false;
+ case 'X':
+ ++read_ptr;
+ if (!ParseExpression()) return false;
+ return Parse('E');
+ case 'L':
+ ++read_ptr;
+ return ParseExpressionPrimary();
+ default:
+ return ParseType();
+ }
+ }
+
+ // <template-args> ::= I <template-arg>* E
+ // extension, the abi says <template-arg>+
+
+ bool ParseTemplateArgs(bool record_template_args = false)
+ {
+ if (record_template_args) ResetTemplateArgs();
+
+ bool first_arg = true;
+ while (*read_ptr != 'E')
+ {
+ 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);
+ }
+ ++read_ptr;
+ return true;
+ }
+
+ // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
+ // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
+ //
+ // <prefix> ::= <prefix> <unqualified-name>
+ // ::= <template-prefix> <template-args>
+ // ::= <template-param>
+ // ::= <decltype>
+ // ::= # empty
+ // ::= <substitution>
+ // ::= <prefix> <data-member-prefix>
+ // extension ::= L
+ //
+ // <template-prefix> ::= <prefix> <template unqualified-name>
+ // ::= <template-param>
+ // ::= <substitution>
+ //
+ // <unqualified-name> ::= <operator-name>
+ // ::= <ctor-dtor-name>
+ // ::= <source-name>
+ // ::= <unnamed-type-name>
+
+ bool ParseNestedName(NameState & name_state, bool parse_discriminator = false)
+ {
+ int qualifiers = TryParseQualifiers(true, true);
+ bool first_part = true;
+ bool suppress_substitution = true;
+ int name_start_cookie = GetStartCookie();
+ while (true)
+ {
+ char next = *read_ptr;
+ if (next == 'E')
+ {
+ ++read_ptr;
+ break;
+ }
+
+ // Record a substitution candidate for all prefixes, but not the full name
+ if (suppress_substitution) suppress_substitution = false;
+ else EndSubstitution(name_start_cookie);
+
+ if (next == 'I')
+ {
+ ++read_ptr;
+ name_state.is_last_generic = true;
+ WriteTemplateStart();
+ if (!ParseTemplateArgs(name_state.parse_function_params)) return false;
+ WriteTemplateEnd();
+ continue;
+ }
+
+ if (first_part) first_part = false;
+ else WriteNamespaceSeparator();
+
+ name_state.is_last_generic = false;
+ switch (next)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ int name_start_cookie = GetStartCookie();
+ if (!ParseSourceName()) return false;
+ name_state.last_name_range = EndRange(name_start_cookie);
+ continue;
+ }
+ case 'S':
+ if (*++read_ptr == 't')
+ {
+ WriteStdPrefix();
+ ++read_ptr;
+ if (!ParseUnqualifiedName(name_state)) return false;
+ }
+ else
+ {
+ if (!ParseSubstitution()) return false;
+ suppress_substitution = true;
+ }
+ continue;
+ case 'T':
+ ++read_ptr;
+ if (!ParseTemplateParam()) return false;
+ continue;
+ case 'C':
+ ++read_ptr;
+ if (!ParseCtor(name_state)) return false;
+ continue;
+ case 'D':
+ {
+ switch (*(read_ptr + 1))
+ {
+ case 't':
+ case 'T':
+#ifdef DEBUG_FAILURES
+ printf("*** Decltype unsupported\n");
+#endif
+ return false;
+ }
+ ++read_ptr;
+ if (!ParseDtor(name_state)) return false;
+ continue;
+ }
+ case 'U':
+ ++read_ptr;
+ if (!ParseUnnamedTypeName(name_state)) return false;
+ continue;
+ case 'L':
+ ++read_ptr;
+ if (!ParseUnqualifiedName(name_state)) return false;
+ continue;
+ default:
+ 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);
+ return true;
+ }
+
+ // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
+ // := Z <function encoding> E s [<discriminator>]
+ // := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
+
+ bool ParseLocalName(bool parse_function_params)
+ {
+ if (!ParseEncoding()) return false;
+ if (!Parse('E')) return false;
+
+ switch (*read_ptr)
+ {
+ case 's':
+ TryParseDiscriminator(); // Optional and ignored
+ WRITE("::string literal");
+ break;
+ case 'd':
+ TryParseNumber(); // Optional and ignored
+ WriteNamespaceSeparator();
+ if (!ParseName()) return false;
+ break;
+ default:
+ WriteNamespaceSeparator();
+ if (!ParseName(parse_function_params, true)) return false;
+ TryParseDiscriminator(); // Optional and ignored
+ }
+ return true;
+ }
+
+ // <name> ::= <nested-name>
+ // ::= <local-name>
+ // ::= <unscoped-template-name> <template-args>
+ // ::= <unscoped-name>
+
+ // <unscoped-template-name> ::= <unscoped-name>
+ // ::= <substitution>
+
+ bool ParseName(bool parse_function_params = false,
+ bool parse_discriminator = false)
+ {
+ NameState name_state = { parse_function_params };
+ int name_start_cookie = GetStartCookie();
+
+ switch (*read_ptr)
+ {
+ case 'N':
+ ++read_ptr;
+ return ParseNestedName(name_state, parse_discriminator);
+ case 'Z':
+ {
+ ++read_ptr;
+ if (!ParseLocalName(parse_function_params)) return false;
+ break;
+ }
+ case 'L':
+ ++read_ptr;
+ // fallthrough
+ default:
+ {
+ if (!ParseUnscopedName(name_state)) return false;
+
+ if (*read_ptr == 'I')
+ {
+ EndSubstitution(name_start_cookie);
+
+ ++read_ptr;
+ name_state.is_last_generic = true;
+ WriteTemplateStart();
+ if (!ParseTemplateArgs(parse_function_params)) return false;
+ WriteTemplateEnd();
+ }
+ break;
+ }
+ }
+ if (parse_discriminator) TryParseDiscriminator();
+ if (parse_function_params &&
+ !ParseFunctionArgs(name_state, name_start_cookie)) return false;
+ return true;
+ }
+
+ // <call-offset> ::= h <nv-offset> _
+ // ::= v <v-offset> _
+ //
+ // <nv-offset> ::= <offset number>
+ // # non-virtual base override
+ //
+ // <v-offset> ::= <offset number> _ <virtual offset number>
+ // # virtual base override, with vcall offset
+
+ bool ParseCallOffset()
+ {
+ switch (*read_ptr++)
+ {
+ case 'h':
+ if (*read_ptr == 'n') ++read_ptr;
+ if (TryParseNumber() == -1 || *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;
+ return true;
+ }
+#ifdef DEBUG_FAILURES
+ printf("*** Malformed call offset\n");
+#endif
+ return false;
+ }
+
+ // <special-name> ::= TV <type> # virtual table
+ // ::= TT <type> # VTT structure (construction vtable index)
+ // ::= TI <type> # typeinfo structure
+ // ::= TS <type> # typeinfo name (null-terminated byte string)
+ // ::= Tc <call-offset> <call-offset> <base encoding>
+ // # base is the nominal target function of thunk
+ // # first call-offset is 'this' adjustment
+ // # second call-offset is result adjustment
+ // ::= T <call-offset> <base encoding>
+ // # base is the nominal target function of thunk
+ // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
+
+ bool ParseSpecialNameT()
+ {
+ switch (*read_ptr++)
+ {
+ case 'V':
+ WRITE("vtable for ");
+ return ParseType();
+ case 'T':
+ WRITE("VTT for ");
+ return ParseType();
+ case 'I':
+ WRITE("typeinfo for ");
+ return ParseType();
+ case 'S':
+ WRITE("typeinfo name for ");
+ return ParseType();
+ case 'c':
+ case 'C':
+#ifdef DEBUG_FAILURES
+ printf("*** Unsupported thunk or construction vtable name: %.3s\n", read_ptr - 1);
+#endif
+ return false;
+ default:
+ if (*--read_ptr == 'v')
+ {
+ WRITE("virtual thunk to ");
+ }
+ else
+ {
+ WRITE("non-virtual thunk to ");
+ }
+ if (!ParseCallOffset()) return false;
+ return ParseEncoding();
+ }
+ }
+
+ // <special-name> ::= GV <object name> # Guard variable for one-time initialization
+ // # No <type>
+ // extension ::= GR <object name> # reference temporary for object
+
+ bool ParseSpecialNameG()
+ {
+ switch (*read_ptr++)
+ {
+ case 'V':
+ WRITE("guard variable for ");
+ if (!ParseName(true)) return false;
+ break;
+ case 'R':
+ WRITE("reference temporary for ");
+ if (!ParseName(true)) return false;
+ break;
+ default:
+#ifdef DEBUG_FAILURES
+ printf("*** Unknown G encoding\n");
+#endif
+ return false;
+ }
+ return true;
+ }
+
+ // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
+
+ bool ParseFunctionArgs(NameState & name_state, int return_insert_cookie)
+ {
+ char next = *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;
+ if (TryParseNumber())
+ {
+ if (*read_ptr == '\0') return true;
+ 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;
+ Write(' ');
+ ReorderRange(EndRange(return_type_start_cookie),
+ return_insert_cookie);
+ }
+
+ Write('(');
+ bool first_param = true;
+ while (true)
+ {
+ switch (*read_ptr)
+ {
+ case '\0':
+ case 'E':
+ case '.':
+ break;
+ case 'v':
+ ++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)
+ {
+ read_ptr += strlen(read_ptr);
+ break;
+ }
+ // fallthrough
+ default:
+ if (first_param) first_param = false;
+ else WriteCommaSpace();
+
+ if (!ParseType()) return false;
+ continue;
+ }
+ break;
+ }
+ Write(')');
+ return true;
+ }
+
+ // <encoding> ::= <function name> <bare-function-type>
+ // ::= <data name>
+ // ::= <special-name>
+
+ bool ParseEncoding()
+ {
+ switch (*read_ptr)
+ {
+ case 'T':
+ ++read_ptr;
+ if (!ParseSpecialNameT()) return false;
+ break;
+ case 'G':
+ ++read_ptr;
+ if (!ParseSpecialNameG()) return false;
+ break;
+ default:
+ 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')
+ {
+#ifdef DEBUG_FAILURES
+ printf("*** Missing _Z prefix\n");
+#endif
+ return false;
+ }
+ if (!ParseEncoding()) return false;
+ switch (*read_ptr)
+ {
+ case '.':
+ Write(' ');
+ Write('(');
+ Write(read_ptr, read_end - read_ptr);
+ Write(')');
+ case '\0':
+ return true;
+ default:
+#ifdef DEBUG_FAILURES
+ printf("*** Unparsed mangled content\n");
+#endif
+ 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;
+
+ // 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;
+};
+
+} // Anonymous namespace
+
+// Public entry points referenced from Mangled.cpp
+namespace lldb_private
+{
+ char * FastDemangle(const char* mangled_name)
+ {
+ char buffer[16384];
+ SymbolDemangler demangler(buffer, sizeof(buffer));
+ return demangler.GetDemangledCopy(mangled_name);
+ }
+
+ char * FastDemangle(const char* mangled_name, long mangled_name_length)
+ {
+ char buffer[16384];
+ SymbolDemangler demangler(buffer, sizeof(buffer));
+ return demangler.GetDemangledCopy(mangled_name, mangled_name_length);
+ }
+} // lldb_private namespace
diff --git a/source/Core/IOHandler.cpp b/source/Core/IOHandler.cpp
index 168a8f67a08e..add3ad8c5ba3 100644
--- a/source/Core/IOHandler.cpp
+++ b/source/Core/IOHandler.cpp
@@ -15,6 +15,7 @@
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObjectRegister.h"
@@ -157,6 +158,7 @@ IOHandlerConfirm::IOHandlerConfirm (Debugger &debugger,
NULL, // NULL editline_name means no history loaded/saved
NULL,
false, // Multi-line
+ 0,
*this),
m_default_response (default_response),
m_user_response (default_response)
@@ -311,6 +313,7 @@ IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
const char *editline_name, // Used for saving history files
const char *prompt,
bool multi_line,
+ uint32_t line_number_start,
IOHandlerDelegate &delegate) :
IOHandlerEditline(debugger,
StreamFileSP(), // Inherit input from top input reader
@@ -320,6 +323,7 @@ IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
editline_name, // Used for saving history files
prompt,
multi_line,
+ line_number_start,
delegate)
{
}
@@ -332,11 +336,13 @@ IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
const char *editline_name, // Used for saving history files
const char *prompt,
bool multi_line,
+ uint32_t line_number_start,
IOHandlerDelegate &delegate) :
IOHandler (debugger, input_sp, output_sp, error_sp, flags),
m_editline_ap (),
m_delegate (delegate),
m_prompt (),
+ m_base_line_number (line_number_start),
m_multi_line (multi_line)
{
SetPrompt(prompt);
@@ -346,16 +352,20 @@ IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
#ifndef _MSC_VER
use_editline = m_input_sp->GetFile().GetIsRealTerminal();
#else
- use_editline = true;
+ // 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);
m_editline_ap->SetAutoCompleteCallback (AutoCompleteCallback, this);
}
@@ -369,11 +379,11 @@ IOHandlerEditline::~IOHandlerEditline ()
bool
-IOHandlerEditline::GetLine (std::string &line)
+IOHandlerEditline::GetLine (std::string &line, bool &interrupted)
{
if (m_editline_ap)
{
- return m_editline_ap->GetLine(line).Success();
+ return m_editline_ap->GetLine(line, interrupted).Success();
}
else
{
@@ -401,7 +411,16 @@ IOHandlerEditline::GetLine (std::string &line)
while (!done)
{
if (fgets(buffer, sizeof(buffer), in) == NULL)
- done = true;
+ {
+ const int saved_errno = errno;
+ if (feof(in))
+ done = true;
+ else if (ferror(in))
+ {
+ if (saved_errno != EINTR)
+ done = true;
+ }
+ }
else
{
got_line = true;
@@ -491,33 +510,62 @@ IOHandlerEditline::SetPrompt (const char *p)
return true;
}
+void
+IOHandlerEditline::SetBaseLineNumber (uint32_t line)
+{
+ m_base_line_number = line;
+ if (m_editline_ap)
+ m_editline_ap->ShowLineNumbers (true, line);
+
+}
bool
-IOHandlerEditline::GetLines (StringList &lines)
+IOHandlerEditline::GetLines (StringList &lines, bool &interrupted)
{
bool success = false;
if (m_editline_ap)
{
std::string end_token;
- success = m_editline_ap->GetLines(end_token, lines).Success();
+ success = m_editline_ap->GetLines(end_token, lines, interrupted).Success();
}
else
{
LineStatus lines_status = LineStatus::Success;
+ Error error;
while (lines_status == LineStatus::Success)
{
+ // Show line numbers if we are asked to
std::string line;
- if (GetLine(line))
+ if (m_base_line_number > 0 && GetIsInteractive())
{
- lines.AppendString(line);
- Error error;
- lines_status = m_delegate.IOHandlerLinesUpdated(*this, lines, lines.GetSize() - 1, error);
+ FILE *out = GetOutputFILE();
+ if (out)
+ ::fprintf(out, "%u%s", m_base_line_number + (uint32_t)lines.GetSize(), GetPrompt() == NULL ? " " : "");
+ }
+
+ bool interrupted = false;
+ if (GetLine(line, interrupted))
+ {
+ if (interrupted)
+ {
+ lines_status = LineStatus::Done;
+ }
+ else
+ {
+ lines.AppendString(line);
+ lines_status = m_delegate.IOHandlerLinesUpdated(*this, lines, lines.GetSize() - 1, error);
+ }
}
else
{
lines_status = LineStatus::Done;
}
}
+
+ // 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;
}
return success;
@@ -532,13 +580,21 @@ IOHandlerEditline::Run ()
std::string line;
while (IsActive())
{
+ bool interrupted = false;
if (m_multi_line)
{
StringList lines;
- if (GetLines (lines))
+ if (GetLines (lines, interrupted))
{
- line = lines.CopyList();
- m_delegate.IOHandlerInputComplete(*this, line);
+ if (interrupted)
+ {
+ m_done = true;
+ }
+ else
+ {
+ line = lines.CopyList();
+ m_delegate.IOHandlerInputComplete(*this, line);
+ }
}
else
{
@@ -547,9 +603,10 @@ IOHandlerEditline::Run ()
}
else
{
- if (GetLine(line))
+ if (GetLine(line, interrupted))
{
- m_delegate.IOHandlerInputComplete(*this, line);
+ if (!interrupted)
+ m_delegate.IOHandlerInputComplete(*this, line);
}
else
{
@@ -562,7 +619,7 @@ IOHandlerEditline::Run ()
void
IOHandlerEditline::Hide ()
{
- if (m_editline_ap && m_editline_ap->GettingLine())
+ if (m_editline_ap)
m_editline_ap->Hide();
}
@@ -570,8 +627,10 @@ IOHandlerEditline::Hide ()
void
IOHandlerEditline::Refresh ()
{
- if (m_editline_ap && m_editline_ap->GettingLine())
+ if (m_editline_ap)
+ {
m_editline_ap->Refresh();
+ }
else
{
const char *prompt = GetPrompt();
@@ -594,11 +653,16 @@ IOHandlerEditline::Cancel ()
m_editline_ap->Interrupt ();
}
-void
+bool
IOHandlerEditline::Interrupt ()
{
+ // Let the delgate handle it first
+ if (m_delegate.IOHandlerInterrupt(*this))
+ return true;
+
if (m_editline_ap)
- m_editline_ap->Interrupt();
+ return m_editline_ap->Interrupt();
+ return false;
}
void
@@ -1308,7 +1372,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
const size_t max_length = help_delegate_ap->GetMaxLineLength();
Rect bounds = GetBounds();
bounds.Inset(1, 1);
- if (max_length + 4 < bounds.size.width)
+ if (max_length + 4 < static_cast<size_t>(bounds.size.width))
{
bounds.origin.x += (bounds.size.width - max_length + 4)/2;
bounds.size.width = max_length + 4;
@@ -1323,7 +1387,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
}
}
- if (num_lines + 2 < bounds.size.height)
+ if (num_lines + 2 < static_cast<size_t>(bounds.size.height))
{
bounds.origin.y += (bounds.size.height - num_lines + 2)/2;
bounds.size.height = num_lines + 2;
@@ -1821,9 +1885,9 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
for (size_t i=0; i<num_submenus; ++i)
{
Menu *submenu = submenus[i].get();
- if (m_max_submenu_name_length < submenu->m_name.size())
+ if (static_cast<size_t>(m_max_submenu_name_length) < submenu->m_name.size())
m_max_submenu_name_length = submenu->m_name.size();
- if (m_max_submenu_key_name_length < submenu->m_key_name.size())
+ if (static_cast<size_t>(m_max_submenu_key_name_length) < submenu->m_key_name.size())
m_max_submenu_key_name_length = submenu->m_key_name.size();
}
}
@@ -1832,9 +1896,9 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
Menu::AddSubmenu (const MenuSP &menu_sp)
{
menu_sp->m_parent = this;
- if (m_max_submenu_name_length < menu_sp->m_name.size())
+ if (static_cast<size_t>(m_max_submenu_name_length) < menu_sp->m_name.size())
m_max_submenu_name_length = menu_sp->m_name.size();
- if (m_max_submenu_key_name_length < menu_sp->m_key_name.size())
+ if (static_cast<size_t>(m_max_submenu_key_name_length) < menu_sp->m_key_name.size())
m_max_submenu_key_name_length = menu_sp->m_key_name.size();
m_submenus.push_back(menu_sp);
}
@@ -1850,7 +1914,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
if (width > 2)
{
width -= 2;
- for (size_t i=0; i< width; ++i)
+ for (int i=0; i< width; ++i)
window.PutChar(ACS_HLINE);
}
window.PutChar(ACS_RTEE);
@@ -1951,7 +2015,8 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
window.Box();
for (size_t i=0; i<num_submenus; ++i)
{
- const bool is_selected = i == selected_idx;
+ const bool is_selected =
+ (i == static_cast<size_t>(selected_idx));
window.MoveCursor(x, y + i);
if (is_selected)
{
@@ -1990,7 +2055,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
case KEY_DOWN:
case KEY_UP:
// Show last menu or first menu
- if (selected_idx < num_submenus)
+ if (selected_idx < static_cast<int>(num_submenus))
run_menu_sp = submenus[selected_idx];
else if (!submenus.empty())
run_menu_sp = submenus.front();
@@ -2000,9 +2065,9 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
case KEY_RIGHT:
{
++m_selected;
- if (m_selected >= num_submenus)
+ if (m_selected >= static_cast<int>(num_submenus))
m_selected = 0;
- if (m_selected < num_submenus)
+ if (m_selected < static_cast<int>(num_submenus))
run_menu_sp = submenus[m_selected];
else if (!submenus.empty())
run_menu_sp = submenus.front();
@@ -2015,7 +2080,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
--m_selected;
if (m_selected < 0)
m_selected = num_submenus - 1;
- if (m_selected < num_submenus)
+ if (m_selected < static_cast<int>(num_submenus))
run_menu_sp = submenus[m_selected];
else if (!submenus.empty())
run_menu_sp = submenus.front();
@@ -2069,7 +2134,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
const int start_select = m_selected;
while (++m_selected != start_select)
{
- if (m_selected >= num_submenus)
+ if (static_cast<size_t>(m_selected) >= num_submenus)
m_selected = 0;
if (m_submenus[m_selected]->GetType() == Type::Separator)
continue;
@@ -2086,7 +2151,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
const int start_select = m_selected;
while (--m_selected != start_select)
{
- if (m_selected < 0)
+ if (m_selected < static_cast<int>(0))
m_selected = num_submenus - 1;
if (m_submenus[m_selected]->GetType() == Type::Separator)
continue;
@@ -2098,7 +2163,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
break;
case KEY_RETURN:
- if (selected_idx < num_submenus)
+ if (static_cast<size_t>(selected_idx) < num_submenus)
{
if (submenus[selected_idx]->Action() == MenuActionResult::Quit)
return eQuitApplication;
@@ -2113,13 +2178,11 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
default:
{
- bool handled = false;
for (size_t i=0; i<num_submenus; ++i)
{
Menu *menu = submenus[i].get();
if (menu->GetKeyValue() == key)
{
- handled = true;
SetSelectedSubmenuIndex(i);
window.GetParent()->RemoveSubWindow(&window);
if (menu->Action() == MenuActionResult::Quit)
@@ -2288,6 +2351,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
ConstString broadcaster_class (broadcaster->GetBroadcasterClass());
if (broadcaster_class == broadcaster_class_process)
{
+ debugger.GetCommandInterpreter().UpdateExecutionContext(NULL);
update = true;
continue; // Don't get any key, just update our view
}
@@ -2302,6 +2366,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
switch (key_result)
{
case eKeyHandled:
+ debugger.GetCommandInterpreter().UpdateExecutionContext(NULL);
update = true;
break;
case eKeyNotHandled:
@@ -2493,6 +2558,7 @@ public:
TreeItem (TreeItem *parent, TreeDelegate &delegate, bool might_have_children) :
m_parent (parent),
m_delegate (delegate),
+ m_user_data (NULL),
m_identifier (0),
m_row_idx (-1),
m_children (),
@@ -2508,6 +2574,7 @@ public:
{
m_parent = rhs.m_parent;
m_delegate = rhs.m_delegate;
+ m_user_data = rhs.m_user_data;
m_identifier = rhs.m_identifier;
m_row_idx = rhs.m_row_idx;
m_children = rhs.m_children;
@@ -2573,11 +2640,14 @@ public:
SetRowIndex(row_idx);
++row_idx;
- // The root item must calculate its children
- if (m_parent == NULL)
+ const bool expanded = IsExpanded();
+
+ // The root item must calculate its children,
+ // or we must calculate the number of children
+ // if the item is expanded
+ if (m_parent == NULL || expanded)
GetNumChildren();
- const bool expanded = IsExpanded();
for (auto &item : m_children)
{
if (expanded)
@@ -2650,7 +2720,8 @@ public:
window.PutChar (ACS_DIAMOND);
window.PutChar (ACS_HLINE);
}
- bool highlight = (selected_row_idx == m_row_idx) && window.IsActive();
+ bool highlight =
+ (selected_row_idx == static_cast<size_t>(m_row_idx)) && window.IsActive();
if (highlight)
window.AttributeOn(A_REVERSE);
@@ -2717,11 +2788,11 @@ public:
TreeItem *
GetItemForRowIndex (uint32_t row_idx)
{
- if (m_row_idx == row_idx)
+ if (static_cast<uint32_t>(m_row_idx) == row_idx)
return this;
if (m_children.empty())
return NULL;
- if (m_children.back().m_row_idx < row_idx)
+ if (static_cast<uint32_t>(m_children.back().m_row_idx) < row_idx)
return NULL;
if (IsExpanded())
{
@@ -2735,17 +2806,18 @@ public:
return NULL;
}
-// void *
-// GetUserData() const
-// {
-// return m_user_data;
-// }
-//
-// void
-// SetUserData (void *user_data)
-// {
-// m_user_data = user_data;
-// }
+ void *
+ GetUserData() const
+ {
+ return m_user_data;
+ }
+
+ void
+ SetUserData (void *user_data)
+ {
+ m_user_data = user_data;
+ }
+
uint64_t
GetIdentifier() const
{
@@ -2759,10 +2831,16 @@ public:
}
+ void
+ SetMightHaveChildren (bool b)
+ {
+ m_might_have_children = b;
+ }
+
protected:
TreeItem *m_parent;
TreeDelegate &m_delegate;
- //void *m_user_data;
+ void *m_user_data;
uint64_t m_identifier;
int m_row_idx; // Zero based visible row index, -1 if not visible or for the root item
std::vector<TreeItem> m_children;
@@ -3004,12 +3082,9 @@ protected:
class FrameTreeDelegate : public TreeDelegate
{
public:
- FrameTreeDelegate (const ThreadSP &thread_sp) :
- TreeDelegate(),
- m_thread_wp()
+ FrameTreeDelegate () :
+ TreeDelegate()
{
- if (thread_sp)
- m_thread_wp = thread_sp;
}
virtual ~FrameTreeDelegate()
@@ -3019,11 +3094,11 @@ public:
virtual void
TreeDelegateDrawTreeItem (TreeItem &item, Window &window)
{
- ThreadSP thread_sp = m_thread_wp.lock();
- if (thread_sp)
+ Thread* thread = (Thread*)item.GetUserData();
+ if (thread)
{
const uint64_t frame_idx = item.GetIdentifier();
- StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(frame_idx);
+ StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_idx);
if (frame_sp)
{
StreamString strm;
@@ -3048,23 +3123,16 @@ public:
virtual bool
TreeDelegateItemSelected (TreeItem &item)
{
- ThreadSP thread_sp = m_thread_wp.lock();
- if (thread_sp)
+ Thread* thread = (Thread*)item.GetUserData();
+ if (thread)
{
+ thread->GetProcess()->GetThreadList().SetSelectedThreadByID(thread->GetID());
const uint64_t frame_idx = item.GetIdentifier();
- thread_sp->SetSelectedFrameByIndex(frame_idx);
+ thread->SetSelectedFrameByIndex(frame_idx);
return true;
}
return false;
}
- void
- SetThread (ThreadSP thread_sp)
- {
- m_thread_wp = thread_sp;
- }
-
-protected:
- ThreadWP m_thread_wp;
};
class ThreadTreeDelegate : public TreeDelegate
@@ -3073,7 +3141,6 @@ public:
ThreadTreeDelegate (Debugger &debugger) :
TreeDelegate(),
m_debugger (debugger),
- m_thread_wp (),
m_tid (LLDB_INVALID_THREAD_ID),
m_stop_id (UINT32_MAX)
{
@@ -3084,10 +3151,25 @@ public:
{
}
+ ProcessSP
+ GetProcess ()
+ {
+ return m_debugger.GetCommandInterpreter().GetExecutionContext().GetProcessSP();
+ }
+
+ ThreadSP
+ GetThread (const TreeItem &item)
+ {
+ ProcessSP process_sp = GetProcess ();
+ if (process_sp)
+ return process_sp->GetThreadList().FindThreadByID(item.GetIdentifier());
+ return ThreadSP();
+ }
+
virtual void
TreeDelegateDrawTreeItem (TreeItem &item, Window &window)
{
- ThreadSP thread_sp = m_thread_wp.lock();
+ ThreadSP thread_sp = GetThread (item);
if (thread_sp)
{
StreamString strm;
@@ -3103,43 +3185,36 @@ public:
virtual void
TreeDelegateGenerateChildren (TreeItem &item)
{
- TargetSP target_sp (m_debugger.GetSelectedTarget());
- if (target_sp)
+ ProcessSP process_sp = GetProcess ();
+ if (process_sp && process_sp->IsAlive())
{
- ProcessSP process_sp = target_sp->GetProcessSP();
- if (process_sp && process_sp->IsAlive())
+ StateType state = process_sp->GetState();
+ if (StateIsStoppedState(state, true))
{
- StateType state = process_sp->GetState();
- if (StateIsStoppedState(state, true))
+ ThreadSP thread_sp = GetThread (item);
+ if (thread_sp)
{
- ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread();
- if (thread_sp)
+ if (m_stop_id == process_sp->GetStopID() && thread_sp->GetID() == m_tid)
+ return; // Children are already up to date
+ if (!m_frame_delegate_sp)
{
- if (m_stop_id == process_sp->GetStopID() && thread_sp->GetID() == m_tid)
- return; // Children are already up to date
- if (m_frame_delegate_sp)
- m_frame_delegate_sp->SetThread(thread_sp);
- else
- {
- // Always expand the thread item the first time we show it
- item.Expand();
- m_frame_delegate_sp.reset (new FrameTreeDelegate(thread_sp));
- }
+ // Always expand the thread item the first time we show it
+ m_frame_delegate_sp.reset (new FrameTreeDelegate());
+ }
- m_stop_id = process_sp->GetStopID();
- m_thread_wp = thread_sp;
- m_tid = thread_sp->GetID();
-
- TreeItem t (&item, *m_frame_delegate_sp, false);
- size_t num_frames = thread_sp->GetStackFrameCount();
- item.Resize (num_frames, t);
- for (size_t i=0; i<num_frames; ++i)
- {
- item[i].SetIdentifier(i);
- }
+ m_stop_id = process_sp->GetStopID();
+ m_tid = thread_sp->GetID();
+
+ TreeItem t (&item, *m_frame_delegate_sp, false);
+ size_t num_frames = thread_sp->GetStackFrameCount();
+ item.Resize (num_frames, t);
+ for (size_t i=0; i<num_frames; ++i)
+ {
+ item[i].SetUserData(thread_sp.get());
+ item[i].SetIdentifier(i);
}
- return;
}
+ return;
}
}
item.ClearChildren();
@@ -3148,16 +3223,24 @@ public:
virtual bool
TreeDelegateItemSelected (TreeItem &item)
{
- ThreadSP thread_sp = m_thread_wp.lock();
- if (thread_sp)
+ ProcessSP process_sp = GetProcess ();
+ if (process_sp && process_sp->IsAlive())
{
- ThreadList &thread_list = thread_sp->GetProcess()->GetThreadList();
- Mutex::Locker locker (thread_list.GetMutex());
- ThreadSP selected_thread_sp = thread_list.GetSelectedThread();
- if (selected_thread_sp->GetID() != thread_sp->GetID())
+ StateType state = process_sp->GetState();
+ if (StateIsStoppedState(state, true))
{
- thread_list.SetSelectedThreadByID(thread_sp->GetID());
- return true;
+ ThreadSP thread_sp = GetThread (item);
+ if (thread_sp)
+ {
+ ThreadList &thread_list = thread_sp->GetProcess()->GetThreadList();
+ Mutex::Locker locker (thread_list.GetMutex());
+ ThreadSP selected_thread_sp = thread_list.GetSelectedThread();
+ if (selected_thread_sp->GetID() != thread_sp->GetID())
+ {
+ thread_list.SetSelectedThreadByID(thread_sp->GetID());
+ return true;
+ }
+ }
}
}
return false;
@@ -3165,12 +3248,100 @@ public:
protected:
Debugger &m_debugger;
- ThreadWP m_thread_wp;
std::shared_ptr<FrameTreeDelegate> m_frame_delegate_sp;
lldb::user_id_t m_tid;
uint32_t m_stop_id;
};
+class ThreadsTreeDelegate : public TreeDelegate
+{
+public:
+ ThreadsTreeDelegate (Debugger &debugger) :
+ TreeDelegate(),
+ m_thread_delegate_sp (),
+ m_debugger (debugger),
+ m_stop_id (UINT32_MAX)
+ {
+ }
+
+ virtual
+ ~ThreadsTreeDelegate()
+ {
+ }
+
+ ProcessSP
+ GetProcess ()
+ {
+ return m_debugger.GetCommandInterpreter().GetExecutionContext().GetProcessSP();
+ }
+
+ virtual void
+ TreeDelegateDrawTreeItem (TreeItem &item, Window &window)
+ {
+ ProcessSP process_sp = GetProcess ();
+ if (process_sp && process_sp->IsAlive())
+ {
+ StreamString strm;
+ ExecutionContext exe_ctx (process_sp);
+ const char *format = "process ${process.id}{, name = ${process.name}}";
+ if (Debugger::FormatPrompt (format, NULL, &exe_ctx, NULL, strm))
+ {
+ int right_pad = 1;
+ window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
+ }
+ }
+ }
+
+ virtual void
+ TreeDelegateGenerateChildren (TreeItem &item)
+ {
+ ProcessSP process_sp = GetProcess ();
+ if (process_sp && process_sp->IsAlive())
+ {
+ StateType state = process_sp->GetState();
+ if (StateIsStoppedState(state, true))
+ {
+ const uint32_t stop_id = process_sp->GetStopID();
+ if (m_stop_id == stop_id)
+ return; // Children are already up to date
+
+ m_stop_id = stop_id;
+
+ if (!m_thread_delegate_sp)
+ {
+ // Always expand the thread item the first time we show it
+ //item.Expand();
+ m_thread_delegate_sp.reset (new ThreadTreeDelegate(m_debugger));
+ }
+
+ TreeItem t (&item, *m_thread_delegate_sp, false);
+ ThreadList &threads = process_sp->GetThreadList();
+ Mutex::Locker locker (threads.GetMutex());
+ size_t num_threads = threads.GetSize();
+ item.Resize (num_threads, t);
+ for (size_t i=0; i<num_threads; ++i)
+ {
+ item[i].SetIdentifier(threads.GetThreadAtIndex(i)->GetID());
+ item[i].SetMightHaveChildren(true);
+ }
+ return;
+ }
+ }
+ item.ClearChildren();
+ }
+
+ virtual bool
+ TreeDelegateItemSelected (TreeItem &item)
+ {
+ return false;
+ }
+
+protected:
+ std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp;
+ Debugger &m_debugger;
+ uint32_t m_stop_id;
+};
+
class ValueObjectListDelegate : public WindowDelegate
{
public:
@@ -3330,7 +3501,7 @@ public:
// Page up key
if (m_first_visible_row > 0)
{
- if (m_first_visible_row > m_max_y)
+ if (static_cast<int>(m_first_visible_row) > m_max_y)
m_first_visible_row -= m_max_y;
else
m_first_visible_row = 0;
@@ -3341,7 +3512,7 @@ public:
case '.':
case KEY_NPAGE:
// Page down key
- if (m_num_rows > m_max_y)
+ if (m_num_rows > static_cast<size_t>(m_max_y))
{
if (m_first_visible_row + m_max_y < m_num_rows)
{
@@ -3508,7 +3679,7 @@ protected:
// Save the row index in each Row structure
row.row_idx = m_num_rows;
if ((m_num_rows >= m_first_visible_row) &&
- ((m_num_rows - m_first_visible_row) < NumVisibleRows()))
+ ((m_num_rows - m_first_visible_row) < static_cast<size_t>(NumVisibleRows())))
{
row.x = m_min_x;
row.y = m_num_rows - m_first_visible_row + 1;
@@ -3880,7 +4051,7 @@ HelpDialogDelegate::WindowDelegateDraw (Window &window, bool force)
int y = 1;
const int min_y = y;
const int max_y = window_height - 1 - y;
- const int num_visible_lines = max_y - min_y + 1;
+ const size_t num_visible_lines = max_y - min_y + 1;
const size_t num_lines = m_text.GetSize();
const char *bottom_message;
if (num_lines <= num_visible_lines)
@@ -3928,7 +4099,7 @@ HelpDialogDelegate::WindowDelegateHandleChar (Window &window, int key)
case ',':
if (m_first_visible_line > 0)
{
- if (m_first_visible_line >= num_visible_lines)
+ if (static_cast<size_t>(m_first_visible_line) >= num_visible_lines)
m_first_visible_line -= num_visible_lines;
else
m_first_visible_line = 0;
@@ -3939,7 +4110,7 @@ HelpDialogDelegate::WindowDelegateHandleChar (Window &window, int key)
if (m_first_visible_line + num_visible_lines < num_lines)
{
m_first_visible_line += num_visible_lines;
- if (m_first_visible_line > num_lines)
+ if (static_cast<size_t>(m_first_visible_line) > num_lines)
m_first_visible_line = num_lines - num_visible_lines;
}
break;
@@ -4071,7 +4242,7 @@ public:
{
Process *process = exe_ctx.GetProcessPtr();
if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true))
- exe_ctx.GetThreadRef().StepIn(true, true);
+ exe_ctx.GetThreadRef().StepIn(true);
}
}
return MenuActionResult::Handled;
@@ -4355,9 +4526,13 @@ public:
if (StateIsStoppedState(state, true))
{
- window.MoveCursor (40, 0);
- if (thread)
- window.Printf ("Thread: 0x%4.4" PRIx64, thread->GetID());
+ StreamString strm;
+ const char *format = "Thread: ${thread.id%tid}";
+ if (thread && Debugger::FormatPrompt (format, NULL, &exe_ctx, NULL, strm))
+ {
+ window.MoveCursor (40, 0);
+ window.PutCStringTruncated(strm.GetString().c_str(), 1);
+ }
window.MoveCursor (60, 0);
if (frame)
@@ -4392,6 +4567,7 @@ public:
m_disassembly_scope (NULL),
m_disassembly_sp (),
m_disassembly_range (),
+ m_title (),
m_line_width (4),
m_selected_line (0),
m_pc_line (0),
@@ -4404,31 +4580,30 @@ public:
m_max_y (0)
{
}
-
-
+
virtual
~SourceFileWindowDelegate()
{
}
-
+
void
Update (const SymbolContext &sc)
{
m_sc = sc;
}
-
+
uint32_t
NumVisibleLines () const
{
return m_max_y - m_min_y;
}
-
+
virtual const char *
WindowDelegateGetHelpText ()
{
return "Source/Disassembly window keyboard shortcuts:";
}
-
+
virtual KeyHelp *
WindowDelegateGetKeyHelp ()
{
@@ -4455,7 +4630,7 @@ public:
};
return g_source_view_key_help;
}
-
+
virtual bool
WindowDelegateDraw (Window &window, bool force)
{
@@ -4473,20 +4648,18 @@ public:
update_location = true;
}
}
-
+
m_min_x = 1;
- m_min_y = 1;
+ m_min_y = 2;
m_max_x = window.GetMaxX()-1;
m_max_y = window.GetMaxY()-1;
-
+
const uint32_t num_visible_lines = NumVisibleLines();
StackFrameSP frame_sp;
bool set_selected_line_to_pc = false;
-
if (update_location)
{
-
const bool process_alive = process ? process->IsAlive() : false;
bool thread_changed = false;
if (process_alive)
@@ -4512,9 +4685,17 @@ public:
const bool stop_id_changed = stop_id != m_stop_id;
bool frame_changed = false;
m_stop_id = stop_id;
+ m_title.Clear();
if (frame_sp)
{
m_sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
+ if (m_sc.module_sp)
+ {
+ m_title.Printf("%s", m_sc.module_sp->GetFileSpec().GetFilename().GetCString());
+ ConstString func_name = m_sc.GetFunctionName();
+ if (func_name)
+ m_title.Printf("`%s", func_name.GetCString());
+ }
const uint32_t frame_idx = frame_sp->GetFrameIndex();
frame_changed = frame_idx != m_frame_idx;
m_frame_idx = frame_idx;
@@ -4525,9 +4706,9 @@ public:
frame_changed = m_frame_idx != UINT32_MAX;
m_frame_idx = UINT32_MAX;
}
-
+
const bool context_changed = thread_changed || frame_changed || stop_id_changed;
-
+
if (process_alive)
{
if (m_sc.line_entry.IsValid())
@@ -4543,7 +4724,7 @@ public:
{
// Same file, nothing to do, we should either have the
// lines or not (source file missing)
- if (m_selected_line >= m_first_visible_line)
+ if (m_selected_line >= static_cast<size_t>(m_first_visible_line))
{
if (m_selected_line >= m_first_visible_line + num_visible_lines)
m_first_visible_line = m_selected_line - 10;
@@ -4567,7 +4748,7 @@ public:
int m_line_width = 1;
for (size_t n = num_lines; n >= 10; n = n / 10)
++m_line_width;
-
+
snprintf (m_line_format, sizeof(m_line_format), " %%%iu ", m_line_width);
if (num_lines < num_visible_lines || m_selected_line < num_visible_lines)
m_first_visible_line = 0;
@@ -4580,7 +4761,7 @@ public:
{
m_file_sp.reset();
}
-
+
if (!m_file_sp || m_file_sp->GetNumLines() == 0)
{
// Show disassembly
@@ -4635,11 +4816,23 @@ public:
m_pc_line = UINT32_MAX;
}
}
-
-
+
+ const int window_width = window.GetWidth();
window.Erase();
window.DrawTitleBox ("Sources");
-
+ if (!m_title.GetString().empty())
+ {
+ window.AttributeOn(A_REVERSE);
+ window.MoveCursor(1, 1);
+ window.PutChar(' ');
+ window.PutCStringTruncated(m_title.GetString().c_str(), 1);
+ int x = window.GetCursorX();
+ if (x < window_width - 1)
+ {
+ window.Printf ("%*s", window_width - x - 1, "");
+ }
+ window.AttributeOff(A_REVERSE);
+ }
Target *target = exe_ctx.GetTargetPtr();
const size_t num_source_lines = GetNumSourceLines();
@@ -4669,17 +4862,16 @@ public:
}
}
}
-
-
+
const attr_t selected_highlight_attr = A_REVERSE;
const attr_t pc_highlight_attr = COLOR_PAIR(1);
- for (int i=0; i<num_visible_lines; ++i)
+ for (size_t i=0; i<num_visible_lines; ++i)
{
const uint32_t curr_line = m_first_visible_line + i;
if (curr_line < num_source_lines)
{
- const int line_y = 1+i;
+ const int line_y = m_min_y+i;
window.MoveCursor(1, line_y);
const bool is_pc_line = curr_line == m_pc_line;
const bool line_is_selected = m_selected_line == curr_line;
@@ -4691,13 +4883,13 @@ public:
highlight_attr = pc_highlight_attr;
else if (line_is_selected)
highlight_attr = selected_highlight_attr;
-
+
if (bp_lines.find(curr_line+1) != bp_lines.end())
bp_attr = COLOR_PAIR(2);
if (bp_attr)
window.AttributeOn(bp_attr);
-
+
window.Printf (m_line_format, curr_line + 1);
if (bp_attr)
@@ -4709,7 +4901,7 @@ public:
window.PutChar(ACS_DIAMOND);
else
window.PutChar(' ');
-
+
if (highlight_attr)
window.AttributeOn(highlight_attr);
const uint32_t line_len = m_file_sp->GetLineLength(curr_line + 1, false);
@@ -4727,15 +4919,15 @@ public:
if (stop_description && stop_description[0])
{
size_t stop_description_len = strlen(stop_description);
- int desc_x = window.GetWidth() - stop_description_len - 16;
+ int desc_x = window_width - stop_description_len - 16;
window.Printf ("%*s", desc_x - window.GetCursorX(), "");
- //window.MoveCursor(window.GetWidth() - stop_description_len - 15, line_y);
+ //window.MoveCursor(window_width - stop_description_len - 15, line_y);
window.Printf ("<<< Thread %u: %s ", thread->GetIndexID(), stop_description);
}
}
else
{
- window.Printf ("%*s", window.GetWidth() - window.GetCursorX() - 1, "");
+ window.Printf ("%*s", window_width - window.GetCursorX() - 1, "");
}
}
if (highlight_attr)
@@ -4777,16 +4969,15 @@ public:
}
}
}
-
-
+
const attr_t selected_highlight_attr = A_REVERSE;
const attr_t pc_highlight_attr = COLOR_PAIR(1);
-
+
StreamString strm;
InstructionList &insts = m_disassembly_sp->GetInstructionList();
Address pc_address;
-
+
if (frame_sp)
pc_address = frame_sp->GetFrameCodeAddress();
const uint32_t pc_idx = pc_address.IsValid() ? insts.GetIndexOfInstructionAtAddress (pc_address) : UINT32_MAX;
@@ -4796,12 +4987,12 @@ public:
}
const uint32_t non_visible_pc_offset = (num_visible_lines / 5);
- if (m_first_visible_line >= num_disassembly_lines)
+ if (static_cast<size_t>(m_first_visible_line) >= num_disassembly_lines)
m_first_visible_line = 0;
if (pc_idx < num_disassembly_lines)
{
- if (pc_idx < m_first_visible_line ||
+ if (pc_idx < static_cast<uint32_t>(m_first_visible_line) ||
pc_idx >= m_first_visible_line + num_visible_lines)
m_first_visible_line = pc_idx - non_visible_pc_offset;
}
@@ -4812,8 +5003,9 @@ public:
Instruction *inst = insts.GetInstructionAtIndex(inst_idx).get();
if (!inst)
break;
-
- window.MoveCursor(1, i+1);
+
+ const int line_y = m_min_y+i;
+ window.MoveCursor(1, line_y);
const bool is_pc_line = frame_sp && inst_idx == pc_idx;
const bool line_is_selected = m_selected_line == inst_idx;
// Highlight the line as the PC line first, then if the selected line
@@ -4824,28 +5016,29 @@ public:
highlight_attr = pc_highlight_attr;
else if (line_is_selected)
highlight_attr = selected_highlight_attr;
-
+
if (bp_file_addrs.find(inst->GetAddress().GetFileAddress()) != bp_file_addrs.end())
bp_attr = COLOR_PAIR(2);
-
+
if (bp_attr)
window.AttributeOn(bp_attr);
-
- window.Printf (" 0x%16.16llx ", inst->GetAddress().GetLoadAddress(target));
-
+
+ window.Printf (" 0x%16.16llx ",
+ static_cast<unsigned long long>(inst->GetAddress().GetLoadAddress(target)));
+
if (bp_attr)
window.AttributeOff(bp_attr);
-
+
window.PutChar(ACS_VLINE);
// Mark the line with the PC with a diamond
if (is_pc_line)
window.PutChar(ACS_DIAMOND);
else
window.PutChar(' ');
-
+
if (highlight_attr)
window.AttributeOn(highlight_attr);
-
+
const char *mnemonic = inst->GetMnemonic(&exe_ctx);
const char *operands = inst->GetOperands(&exe_ctx);
const char *comment = inst->GetComment(&exe_ctx);
@@ -4856,7 +5049,7 @@ public:
operands = NULL;
if (comment && comment[0] == '\0')
comment = NULL;
-
+
strm.Clear();
if (mnemonic && operands && comment)
@@ -4865,10 +5058,10 @@ public:
strm.Printf ("%-8s %s", mnemonic, operands);
else if (mnemonic)
strm.Printf ("%s", mnemonic);
-
+
int right_pad = 1;
window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
-
+
if (is_pc_line && frame_sp && frame_sp->GetConcreteFrameIndex() == 0)
{
StopInfoSP stop_info_sp;
@@ -4880,15 +5073,15 @@ public:
if (stop_description && stop_description[0])
{
size_t stop_description_len = strlen(stop_description);
- int desc_x = window.GetWidth() - stop_description_len - 16;
+ int desc_x = window_width - stop_description_len - 16;
window.Printf ("%*s", desc_x - window.GetCursorX(), "");
- //window.MoveCursor(window.GetWidth() - stop_description_len - 15, line_y);
+ //window.MoveCursor(window_width - stop_description_len - 15, line_y);
window.Printf ("<<< Thread %u: %s ", thread->GetIndexID(), stop_description);
}
}
else
{
- window.Printf ("%*s", window.GetWidth() - window.GetCursorX() - 1, "");
+ window.Printf ("%*s", window_width - window.GetCursorX() - 1, "");
}
}
if (highlight_attr)
@@ -4899,7 +5092,7 @@ public:
window.DeferredRefresh();
return true; // Drawing handled
}
-
+
size_t
GetNumLines ()
{
@@ -4908,7 +5101,7 @@ public:
num_lines = GetNumDisassemblyLines();
return num_lines;
}
-
+
size_t
GetNumSourceLines () const
{
@@ -4935,13 +5128,13 @@ public:
case ',':
case KEY_PPAGE:
// Page up key
- if (m_first_visible_line > num_visible_lines)
+ if (static_cast<uint32_t>(m_first_visible_line) > num_visible_lines)
m_first_visible_line -= num_visible_lines;
else
m_first_visible_line = 0;
m_selected_line = m_first_visible_line;
return eKeyHandled;
-
+
case '.':
case KEY_NPAGE:
// Page down key
@@ -4955,12 +5148,12 @@ public:
m_selected_line = m_first_visible_line;
}
return eKeyHandled;
-
+
case KEY_UP:
if (m_selected_line > 0)
{
m_selected_line--;
- if (m_first_visible_line > m_selected_line)
+ if (static_cast<size_t>(m_first_visible_line) > m_selected_line)
m_first_visible_line = m_selected_line;
}
return eKeyHandled;
@@ -4973,7 +5166,7 @@ public:
m_first_visible_line++;
}
return eKeyHandled;
-
+
case '\r':
case '\n':
case KEY_ENTER:
@@ -5067,7 +5260,7 @@ public:
exe_ctx.GetProcessRef().Resume();
}
return eKeyHandled;
-
+
case 'o':
// 'o' == step out
{
@@ -5096,12 +5289,11 @@ public:
if (exe_ctx.HasThreadScope() && StateIsStoppedState (exe_ctx.GetProcessRef().GetState(), true))
{
bool source_step = (c == 's');
- bool avoid_code_without_debug_info = true;
- exe_ctx.GetThreadRef().StepIn(source_step, avoid_code_without_debug_info);
+ exe_ctx.GetThreadRef().StepIn(source_step);
}
}
return eKeyHandled;
-
+
case 'h':
window.CreateHelpSubwindow ();
return eKeyHandled;
@@ -5111,7 +5303,7 @@ public:
}
return eKeyNotHandled;
}
-
+
protected:
typedef std::set<uint32_t> BreakpointLines;
typedef std::set<lldb::addr_t> BreakpointAddrs;
@@ -5122,6 +5314,7 @@ protected:
SymbolContextScope *m_disassembly_scope;
lldb::DisassemblerSP m_disassembly_sp;
AddressRange m_disassembly_range;
+ StreamString m_title;
lldb::user_id_t m_tid;
char m_line_format[8];
int m_line_width;
@@ -5235,7 +5428,7 @@ IOHandlerCursesGUI::Activate ()
main_window_sp->SetDelegate (std::static_pointer_cast<WindowDelegate>(app_delegate_sp));
source_window_sp->SetDelegate (WindowDelegateSP(new SourceFileWindowDelegate(m_debugger)));
variables_window_sp->SetDelegate (WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
- TreeDelegateSP thread_delegate_sp (new ThreadTreeDelegate(m_debugger));
+ TreeDelegateSP thread_delegate_sp (new ThreadsTreeDelegate(m_debugger));
threads_window_sp->SetDelegate (WindowDelegateSP(new TreeWindowDelegate(m_debugger, thread_delegate_sp)));
status_window_sp->SetDelegate (WindowDelegateSP(new StatusBarWindowDelegate(m_debugger)));
@@ -5291,9 +5484,10 @@ IOHandlerCursesGUI::Cancel ()
{
}
-void
+bool
IOHandlerCursesGUI::Interrupt ()
{
+ return false;
}
@@ -5302,4 +5496,4 @@ IOHandlerCursesGUI::GotEOF()
{
}
-#endif // #ifndef LLDB_DISABLE_CURSES \ No newline at end of file
+#endif // #ifndef LLDB_DISABLE_CURSES
diff --git a/source/Core/Language.cpp b/source/Core/Language.cpp
index af62af37da0d..1ffd5aadc526 100644
--- a/source/Core/Language.cpp
+++ b/source/Core/Language.cpp
@@ -10,6 +10,7 @@
#include "lldb/lldb-private.h"
#include "lldb/Core/Language.h"
#include "lldb/Core/Stream.h"
+#include "llvm/ADT/STLExtras.h"
#include <string.h>
using namespace lldb;
@@ -48,8 +49,7 @@ g_languages[] =
{ { "python" , NULL , "Python" } }
};
-static const size_t
-g_num_languages = sizeof(g_languages)/sizeof(LanguageStrings);
+static const size_t g_num_languages = llvm::array_lengthof(g_languages);
Language::Language(LanguageType language) :
m_language (language)
diff --git a/source/Core/Listener.cpp b/source/Core/Listener.cpp
index aca2b374092e..f71d766e0a1c 100644
--- a/source/Core/Listener.cpp
+++ b/source/Core/Listener.cpp
@@ -34,21 +34,23 @@ Listener::Listener(const char *name) :
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p Listener::Listener('%s')", this, m_name.c_str());
+ log->Printf ("%p Listener::Listener('%s')",
+ static_cast<void*>(this), m_name.c_str());
}
Listener::~Listener()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Mutex::Locker locker (m_broadcasters_mutex);
-
+
size_t num_managers = m_broadcaster_managers.size();
-
+
for (size_t i = 0; i < num_managers; i++)
m_broadcaster_managers[i]->RemoveListener(*this);
-
+
if (log)
- log->Printf ("%p Listener::~Listener('%s')", this, m_name.c_str());
+ log->Printf ("%p Listener::~Listener('%s')",
+ static_cast<void*>(this), m_name.c_str());
Clear();
}
@@ -87,11 +89,9 @@ Listener::StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
if (log)
log->Printf ("%p Listener::StartListeningForEvents (broadcaster = %p, mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
- this,
- broadcaster,
- event_mask,
- acquired_mask,
- m_name.c_str());
+ static_cast<void*>(this),
+ static_cast<void*>(broadcaster), event_mask,
+ acquired_mask, m_name.c_str());
return acquired_mask;
@@ -115,8 +115,14 @@ Listener::StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
if (log)
+ {
+ void **pointer = reinterpret_cast<void**>(&callback);
log->Printf ("%p Listener::StartListeningForEvents (broadcaster = %p, mask = 0x%8.8x, callback = %p, user_data = %p) acquired_mask = 0x%8.8x for %s",
- this, broadcaster, event_mask, callback, callback_user_data, acquired_mask, m_name.c_str());
+ static_cast<void*>(this),
+ static_cast<void*>(broadcaster), event_mask, *pointer,
+ static_cast<void*>(callback_user_data), acquired_mask,
+ m_name.c_str());
+ }
return acquired_mask;
}
@@ -140,7 +146,7 @@ Listener::StopListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask)
return false;
}
-// Called when a Broadcaster is in its destuctor. We need to remove all
+// Called when a Broadcaster is in its destructor. We need to remove all
// knowledge of this broadcaster and any events that it may have queued up
void
Listener::BroadcasterWillDestruct (Broadcaster *broadcaster)
@@ -185,7 +191,9 @@ Listener::AddEvent (EventSP &event_sp)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
if (log)
- log->Printf ("%p Listener('%s')::AddEvent (event_sp = {%p})", this, m_name.c_str(), event_sp.get());
+ log->Printf ("%p Listener('%s')::AddEvent (event_sp = {%p})",
+ static_cast<void*>(this), m_name.c_str(),
+ static_cast<void*>(event_sp.get()));
// Scope for "locker"
{
@@ -292,17 +300,14 @@ Listener::FindNextEventInternal
if (pos != m_events.end())
{
event_sp = *pos;
-
+
if (log)
log->Printf ("%p '%s' Listener::FindNextEventInternal(broadcaster=%p, broadcaster_names=%p[%u], event_type_mask=0x%8.8x, remove=%i) event %p",
- this,
- GetName(),
- broadcaster,
- broadcaster_names,
- num_broadcaster_names,
- event_type_mask,
- remove,
- event_sp.get());
+ static_cast<void*>(this), GetName(),
+ static_cast<void*>(broadcaster),
+ static_cast<const void*>(broadcaster_names),
+ num_broadcaster_names, event_type_mask, remove,
+ static_cast<void*>(event_sp.get()));
if (remove)
{
@@ -311,16 +316,16 @@ Listener::FindNextEventInternal
if (m_events.empty())
m_cond_wait.SetValue (false, eBroadcastNever);
}
-
+
// Unlock the event queue here. We've removed this event and are about to return
// it so it should be okay to get the next event off the queue here - and it might
// be useful to do that in the "DoOnRemoval".
lock.Unlock();
-
+
// Don't call DoOnRemoval if you aren't removing the event...
if (remove)
event_sp->DoOnRemoval();
-
+
return true;
}
@@ -404,10 +409,9 @@ Listener::WaitForEventsInternal
bool timed_out = false;
if (log)
- {
log->Printf ("%p Listener::WaitForEventsInternal (timeout = { %p }) for %s",
- this, timeout, m_name.c_str());
- }
+ static_cast<void*>(this), static_cast<const void*>(timeout),
+ m_name.c_str());
while (1)
{
@@ -421,7 +425,7 @@ Listener::WaitForEventsInternal
// added that might meet our current filter
// But first poll for any new event that might satisfy our condition, and if so consume it,
// otherwise wait.
-
+
Mutex::Locker event_locker(m_events_mutex);
const bool remove = false;
if (FindNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, remove))
@@ -437,14 +441,16 @@ Listener::WaitForEventsInternal
{
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
if (log)
- log->Printf ("%p Listener::WaitForEventsInternal() timed out for %s", this, m_name.c_str());
+ log->Printf ("%p Listener::WaitForEventsInternal() timed out for %s",
+ static_cast<void*>(this), m_name.c_str());
break;
}
else
{
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
if (log)
- log->Printf ("%p Listener::WaitForEventsInternal() unknown error for %s", this, m_name.c_str());
+ log->Printf ("%p Listener::WaitForEventsInternal() unknown error for %s",
+ static_cast<void*>(this), m_name.c_str());
break;
}
}
diff --git a/source/Core/Log.cpp b/source/Core/Log.cpp
index b7dc056af6ce..3adca6e5385c 100644
--- a/source/Core/Log.cpp
+++ b/source/Core/Log.cpp
@@ -110,7 +110,7 @@ Log::PrintfWithFlagsVarArg (uint32_t flags, const char *format, va_list args)
if (m_options.Test (LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD))
header.Printf ("[%4.4x/%4.4" PRIx64 "]: ", getpid(), Host::GetCurrentThreadID());
- // Add the process and thread if requested
+ // 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()));
diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp
index 55bd3cbb8e99..c4fa10fedd86 100644
--- a/source/Core/Mangled.cpp
+++ b/source/Core/Mangled.cpp
@@ -20,6 +20,14 @@
#ifdef LLDB_USE_BUILTIN_DEMANGLER
+// Provide a fast-path demangler implemented in FastDemangle.cpp until it can
+// replace the existing C++ demangler with a complete implementation
+namespace lldb_private
+{
+ extern char * FastDemangle (const char * mangled_name,
+ long mangled_name_length);
+}
+
//----------------------------------------------------------------------
// Inlined copy of:
// http://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp
@@ -3932,15 +3940,15 @@ parse_nested_name(const char* first, const char* last, C& db)
const char* t0 = parse_cv_qualifiers(first+1, last, cv);
if (t0 == last)
return first;
- db.ref = 0;
+ unsigned ref = 0;
if (*t0 == 'R')
{
- db.ref = 1;
+ ref = 1;
++t0;
}
else if (*t0 == 'O')
{
- db.ref = 2;
+ ref = 2;
++t0;
}
db.names.emplace_back();
@@ -4054,6 +4062,7 @@ parse_nested_name(const char* first, const char* last, C& db)
}
}
first = t0 + 1;
+ db.ref = ref;
db.cv = cv;
if (pop_subs && !db.subs.empty())
db.subs.pop_back();
@@ -4413,7 +4422,7 @@ parse_special_name(const char* first, const char* last, C& db)
{
if (db.names.empty())
return first;
- if (first[2] == 'v')
+ if (first[1] == 'v')
{
db.names.back().first.insert(0, "virtual thunk to ");
first = t;
@@ -5128,7 +5137,6 @@ Mangled::SetValue (const ConstString &name)
}
}
-
//----------------------------------------------------------------------
// Generate the demangled name on demand using this accessor. Code in
// this class will need to use this accessor if it wishes to decode
@@ -5157,7 +5165,13 @@ Mangled::GetDemangledName () const
// We didn't already mangle this name, demangle it and if all goes well
// add it to our map.
#ifdef LLDB_USE_BUILTIN_DEMANGLER
- char *demangled_name = __cxa_demangle (mangled_cstr, NULL, NULL, NULL);
+ // Try to use the fast-path demangler first for the
+ // performance win, falling back to the full demangler only
+ // when necessary
+ char *demangled_name = FastDemangle (mangled_cstr,
+ m_mangled.GetLength());
+ if (!demangled_name)
+ demangled_name = __cxa_demangle (mangled_cstr, NULL, NULL, NULL);
#elif defined(_MSC_VER)
// Cannot demangle on msvc.
char *demangled_name = nullptr;
@@ -5242,7 +5256,8 @@ Mangled::Dump (Stream *s) const
void
Mangled::DumpDebug (Stream *s) const
{
- s->Printf("%*p: Mangled mangled = ", (int)sizeof(void*) * 2, this);
+ s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void*) * 2),
+ static_cast<const void*>(this));
m_mangled.DumpDebug(s);
s->Printf(", demangled = ");
m_demangled.DumpDebug(s);
diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp
index d5758c09b1e2..6f16ada49824 100644
--- a/source/Core/Module.cpp
+++ b/source/Core/Module.cpp
@@ -37,6 +37,8 @@
#include "lldb/Target/Target.h"
#include "lldb/Symbol/SymbolFile.h"
+#include "Plugins/ObjectFile/JIT/ObjectFileJIT.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -131,20 +133,21 @@ namespace lldb {
Module::Module (const ModuleSpec &module_spec) :
m_mutex (Mutex::eMutexTypeRecursive),
- m_mod_time (module_spec.GetFileSpec().GetModificationTime()),
- m_arch (module_spec.GetArchitecture()),
+ m_mod_time (),
+ m_arch (),
m_uuid (),
- m_file (module_spec.GetFileSpec()),
- m_platform_file(module_spec.GetPlatformFileSpec()),
+ m_file (),
+ m_platform_file(),
m_remote_install_file(),
- m_symfile_spec (module_spec.GetSymbolFileSpec()),
- m_object_name (module_spec.GetObjectName()),
- m_object_offset (module_spec.GetObjectOffset()),
- m_object_mod_time (module_spec.GetObjectModificationTime()),
+ m_symfile_spec (),
+ m_object_name (),
+ m_object_offset (),
+ m_object_mod_time (),
m_objfile_sp (),
m_symfile_ap (),
m_ast (),
m_source_mappings (),
+ m_sections_ap(),
m_did_load_objfile (false),
m_did_load_symbol_vendor (false),
m_did_parse_uuid (false),
@@ -158,22 +161,81 @@ Module::Module (const ModuleSpec &module_spec) :
Mutex::Locker locker (GetAllocationModuleCollectionMutex());
GetModuleCollection().push_back(this);
}
-
+
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT|LIBLLDB_LOG_MODULES));
if (log)
log->Printf ("%p Module::Module((%s) '%s%s%s%s')",
- this,
- m_arch.GetArchitectureName(),
- m_file.GetPath().c_str(),
- m_object_name.IsEmpty() ? "" : "(",
- m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""),
- m_object_name.IsEmpty() ? "" : ")");
+ static_cast<void*>(this),
+ module_spec.GetArchitecture().GetArchitectureName(),
+ module_spec.GetFileSpec().GetPath().c_str(),
+ module_spec.GetObjectName().IsEmpty() ? "" : "(",
+ module_spec.GetObjectName().IsEmpty() ? "" : module_spec.GetObjectName().AsCString(""),
+ module_spec.GetObjectName().IsEmpty() ? "" : ")");
+
+ // First extract all module specifications from the file using the local
+ // file path. If there are no specifications, then don't fill anything in
+ ModuleSpecList modules_specs;
+ if (ObjectFile::GetModuleSpecifications(module_spec.GetFileSpec(), 0, 0, modules_specs) == 0)
+ return;
+
+ // Now make sure that one of the module specifications matches what we just
+ // extract. We might have a module specification that specifies a file "/usr/lib/dyld"
+ // with UUID XXX, but we might have a local version of "/usr/lib/dyld" that has
+ // UUID YYY and we don't want those to match. If they don't match, just don't
+ // fill any ivars in so we don't accidentally grab the wrong file later since
+ // they don't match...
+ ModuleSpec matching_module_spec;
+ if (modules_specs.FindMatchingModuleSpec(module_spec, matching_module_spec) == 0)
+ return;
+
+ if (module_spec.GetFileSpec())
+ m_mod_time = module_spec.GetFileSpec().GetModificationTime();
+ else if (matching_module_spec.GetFileSpec())
+ m_mod_time = matching_module_spec.GetFileSpec().GetModificationTime();
+
+ // Copy the architecture from the actual spec if we got one back, else use the one that was specified
+ if (matching_module_spec.GetArchitecture().IsValid())
+ m_arch = matching_module_spec.GetArchitecture();
+ else if (module_spec.GetArchitecture().IsValid())
+ m_arch = module_spec.GetArchitecture();
+
+ // Copy the file spec over and use the specified one (if there was one) so we
+ // don't use a path that might have gotten resolved a path in 'matching_module_spec'
+ if (module_spec.GetFileSpec())
+ m_file = module_spec.GetFileSpec();
+ else if (matching_module_spec.GetFileSpec())
+ m_file = matching_module_spec.GetFileSpec();
+
+ // Copy the platform file spec over
+ if (module_spec.GetPlatformFileSpec())
+ m_platform_file = module_spec.GetPlatformFileSpec();
+ else if (matching_module_spec.GetPlatformFileSpec())
+ m_platform_file = matching_module_spec.GetPlatformFileSpec();
+
+ // Copy the symbol file spec over
+ if (module_spec.GetSymbolFileSpec())
+ m_symfile_spec = module_spec.GetSymbolFileSpec();
+ else if (matching_module_spec.GetSymbolFileSpec())
+ m_symfile_spec = matching_module_spec.GetSymbolFileSpec();
+
+ // Copy the object name over
+ if (matching_module_spec.GetObjectName())
+ m_object_name = matching_module_spec.GetObjectName();
+ else
+ m_object_name = module_spec.GetObjectName();
+
+ // Always trust the object offset (file offset) and object modification
+ // time (for mod time in a BSD static archive) of from the matching
+ // module specification
+ m_object_offset = matching_module_spec.GetObjectOffset();
+ m_object_mod_time = matching_module_spec.GetObjectModificationTime();
+
}
Module::Module(const FileSpec& file_spec,
const ArchSpec& arch,
const ConstString *object_name,
- off_t object_offset,
+ lldb::offset_t object_offset,
const TimeValue *object_mod_time_ptr) :
m_mutex (Mutex::eMutexTypeRecursive),
m_mod_time (file_spec.GetModificationTime()),
@@ -190,6 +252,7 @@ Module::Module(const FileSpec& file_spec,
m_symfile_ap (),
m_ast (),
m_source_mappings (),
+ m_sections_ap(),
m_did_load_objfile (false),
m_did_load_symbol_vendor (false),
m_did_parse_uuid (false),
@@ -206,21 +269,49 @@ Module::Module(const FileSpec& file_spec,
if (object_name)
m_object_name = *object_name;
-
+
if (object_mod_time_ptr)
m_object_mod_time = *object_mod_time_ptr;
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT|LIBLLDB_LOG_MODULES));
if (log)
log->Printf ("%p Module::Module((%s) '%s%s%s%s')",
- this,
- m_arch.GetArchitectureName(),
+ static_cast<void*>(this), m_arch.GetArchitectureName(),
m_file.GetPath().c_str(),
m_object_name.IsEmpty() ? "" : "(",
m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""),
m_object_name.IsEmpty() ? "" : ")");
}
+Module::Module () :
+ m_mutex (Mutex::eMutexTypeRecursive),
+ m_mod_time (),
+ m_arch (),
+ m_uuid (),
+ m_file (),
+ m_platform_file(),
+ m_remote_install_file (),
+ m_symfile_spec (),
+ m_object_name (),
+ m_object_offset (0),
+ m_object_mod_time (),
+ m_objfile_sp (),
+ m_symfile_ap (),
+ m_ast (),
+ m_source_mappings (),
+ m_sections_ap(),
+ m_did_load_objfile (false),
+ m_did_load_symbol_vendor (false),
+ m_did_parse_uuid (false),
+ m_did_init_ast (false),
+ m_is_dynamic_loader_module (false),
+ m_file_has_changed (false),
+ m_first_file_changed_log (false)
+{
+ Mutex::Locker locker (GetAllocationModuleCollectionMutex());
+ GetModuleCollection().push_back(this);
+}
+
Module::~Module()
{
// Lock our module down while we tear everything down to make sure
@@ -238,7 +329,7 @@ Module::~Module()
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT|LIBLLDB_LOG_MODULES));
if (log)
log->Printf ("%p Module::~Module((%s) '%s%s%s%s')",
- this,
+ static_cast<void*>(this),
m_arch.GetArchitectureName(),
m_file.GetPath().c_str(),
m_object_name.IsEmpty() ? "" : "(",
@@ -255,7 +346,7 @@ Module::~Module()
}
ObjectFile *
-Module::GetMemoryObjectFile (const lldb::ProcessSP &process_sp, lldb::addr_t header_addr, Error &error)
+Module::GetMemoryObjectFile (const lldb::ProcessSP &process_sp, lldb::addr_t header_addr, Error &error, size_t size_to_read)
{
if (m_objfile_sp)
{
@@ -267,13 +358,13 @@ Module::GetMemoryObjectFile (const lldb::ProcessSP &process_sp, lldb::addr_t hea
if (process_sp)
{
m_did_load_objfile = true;
- std::unique_ptr<DataBufferHeap> data_ap (new DataBufferHeap (512, 0));
+ std::unique_ptr<DataBufferHeap> data_ap (new DataBufferHeap (size_to_read, 0));
Error readmem_error;
const size_t bytes_read = process_sp->ReadMemory (header_addr,
data_ap->GetBytes(),
data_ap->GetByteSize(),
readmem_error);
- if (bytes_read == 512)
+ if (bytes_read == size_to_read)
{
DataBufferSP data_sp(data_ap.release());
m_objfile_sp = ObjectFile::FindPlugin(shared_from_this(), process_sp, header_addr, data_sp);
@@ -342,6 +433,7 @@ Module::GetClangASTContext ()
&& object_arch.GetTriple().getOS() == llvm::Triple::UnknownOS)
{
if (object_arch.GetTriple().getArch() == llvm::Triple::arm ||
+ object_arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
object_arch.GetTriple().getArch() == llvm::Triple::thumb)
{
object_arch.GetTriple().setOS(llvm::Triple::IOS);
@@ -410,14 +502,16 @@ Module::CalculateSymbolContextModule ()
void
Module::DumpSymbolContext(Stream *s)
{
- s->Printf(", Module{%p}", this);
+ s->Printf(", Module{%p}", static_cast<void*>(this));
}
size_t
Module::GetNumCompileUnits()
{
Mutex::Locker locker (m_mutex);
- Timer scoped_timer(__PRETTY_FUNCTION__, "Module::GetNumCompileUnits (module = %p)", this);
+ Timer scoped_timer(__PRETTY_FUNCTION__,
+ "Module::GetNumCompileUnits (module = %p)",
+ static_cast<void*>(this));
SymbolVendor *symbols = GetSymbolVendor ();
if (symbols)
return symbols->GetNumCompileUnits();
@@ -909,7 +1003,7 @@ Module::FindTypes (const SymbolContext& sc,
// Check if "name" starts with "::" which means the qualified type starts
// from the root namespace and implies and exact match. The typenames we
// get back from clang do not start with "::" so we need to strip this off
- // in order to get the qualfied names to match
+ // in order to get the qualified names to match
if (type_scope.size() >= 2 && type_scope[0] == ':' && type_scope[1] == ':')
{
@@ -930,7 +1024,7 @@ Module::FindTypes (const SymbolContext& sc,
{
// The "type_name_cstr" will have been modified if we have a valid type class
// prefix (like "struct", "class", "union", "typedef" etc).
- num_matches = FindTypes_Impl(sc, ConstString(type_name_cstr), NULL, append, max_matches, types);
+ FindTypes_Impl(sc, ConstString(type_name_cstr), NULL, append, max_matches, types);
types.RemoveMismatchedTypes (type_class);
num_matches = types.GetSize();
}
@@ -1233,6 +1327,17 @@ Module::GetSectionList()
return m_sections_ap.get();
}
+void
+Module::SectionFileAddressesChanged ()
+{
+ ObjectFile *obj_file = GetObjectFile ();
+ if (obj_file)
+ obj_file->SectionFileAddressesChanged ();
+ SymbolVendor* sym_vendor = GetSymbolVendor();
+ if (sym_vendor)
+ sym_vendor->SectionFileAddressesChanged ();
+}
+
SectionList *
Module::GetUnifiedSectionList()
{
@@ -1422,7 +1527,10 @@ Module::LoadScriptingResourceInTarget (Target *target, Error& error, Stream* fee
return false;
}
- LoadScriptFromSymFile shoud_load = target->TargetProperties::GetLoadScriptFromSymbolFile();
+ LoadScriptFromSymFile should_load = target->TargetProperties::GetLoadScriptFromSymbolFile();
+
+ if (should_load == eLoadScriptFromSymFileFalse)
+ return false;
Debugger &debugger = target->GetDebugger();
const ScriptLanguage script_language = debugger.GetScriptLanguage();
@@ -1438,7 +1546,8 @@ Module::LoadScriptingResourceInTarget (Target *target, Error& error, Stream* fee
}
FileSpecList file_specs = platform_sp->LocateExecutableScriptingResources (target,
- *this);
+ *this,
+ feedback_stream);
const uint32_t num_specs = file_specs.GetSize();
@@ -1452,9 +1561,7 @@ Module::LoadScriptingResourceInTarget (Target *target, Error& error, Stream* fee
FileSpec scripting_fspec (file_specs.GetFileSpecAtIndex(i));
if (scripting_fspec && scripting_fspec.Exists())
{
- if (shoud_load == eLoadScriptFromSymFileFalse)
- return false;
- if (shoud_load == eLoadScriptFromSymFileWarn)
+ if (should_load == eLoadScriptFromSymFileWarn)
{
if (feedback_stream)
feedback_stream->Printf("warning: '%s' contains a debug script. To run this script in "
@@ -1584,7 +1691,7 @@ Module::GetVersion (uint32_t *versions, uint32_t num_versions)
if (versions && num_versions)
{
for (uint32_t i=0; i<num_versions; ++i)
- versions[i] = UINT32_MAX;
+ versions[i] = LLDB_INVALID_MODULE_VERSION;
}
return 0;
}
@@ -1644,7 +1751,7 @@ Module::PrepareForFunctionNameLookup (const ConstString &name,
if (!cpp_method.GetQualifiers().empty())
{
- // There is a "const" or other qualifer following the end of the fucntion parens,
+ // There is a "const" or other qualifier following the end of the function parens,
// this can't be a eFunctionNameTypeBase
lookup_name_type_mask &= ~(eFunctionNameTypeBase);
if (lookup_name_type_mask == eFunctionNameTypeNone)
@@ -1693,3 +1800,27 @@ Module::PrepareForFunctionNameLookup (const ConstString &name,
match_name_after_lookup = false;
}
}
+
+ModuleSP
+Module::CreateJITModule (const lldb::ObjectFileJITDelegateSP &delegate_sp)
+{
+ if (delegate_sp)
+ {
+ // Must create a module and place it into a shared pointer before
+ // we can create an object file since it has a std::weak_ptr back
+ // to the module, so we need to control the creation carefully in
+ // this static function
+ ModuleSP module_sp(new Module());
+ module_sp->m_objfile_sp.reset (new ObjectFileJIT (module_sp, delegate_sp));
+ if (module_sp->m_objfile_sp)
+ {
+ // Once we get the object file, update our module with the object file's
+ // architecture since it might differ in vendor/os if some parts were
+ // unknown.
+ module_sp->m_objfile_sp->GetArchitecture (module_sp->m_arch);
+ }
+ return module_sp;
+ }
+ return ModuleSP();
+}
+
diff --git a/source/Core/ModuleList.cpp b/source/Core/ModuleList.cpp
index 215611e42429..156f3cf9d0aa 100644
--- a/source/Core/ModuleList.cpp
+++ b/source/Core/ModuleList.cpp
@@ -10,7 +10,11 @@
#include "lldb/Core/ModuleList.h"
// C Includes
+#include <stdint.h>
+
// C++ Includes
+#include <mutex> // std::once
+
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Log.h"
@@ -40,7 +44,8 @@ ModuleList::ModuleList() :
//----------------------------------------------------------------------
ModuleList::ModuleList(const ModuleList& rhs) :
m_modules(),
- m_modules_mutex (Mutex::eMutexTypeRecursive)
+ m_modules_mutex (Mutex::eMutexTypeRecursive),
+ m_notifier(NULL)
{
Mutex::Locker lhs_locker(m_modules_mutex);
Mutex::Locker rhs_locker(rhs.m_modules_mutex);
@@ -62,9 +67,28 @@ ModuleList::operator= (const ModuleList& rhs)
{
if (this != &rhs)
{
- Mutex::Locker lhs_locker(m_modules_mutex);
- Mutex::Locker rhs_locker(rhs.m_modules_mutex);
- m_modules = rhs.m_modules;
+ // That's probably me nit-picking, but in theoretical situation:
+ //
+ // * that two threads A B and
+ // * two ModuleList's x y do opposite assignemnts ie.:
+ //
+ // in thread A: | in thread B:
+ // x = y; | y = x;
+ //
+ // This establishes correct(same) lock taking order and thus
+ // avoids priority inversion.
+ if (uintptr_t(this) > uintptr_t(&rhs))
+ {
+ Mutex::Locker lhs_locker(m_modules_mutex);
+ Mutex::Locker rhs_locker(rhs.m_modules_mutex);
+ m_modules = rhs.m_modules;
+ }
+ else
+ {
+ Mutex::Locker rhs_locker(rhs.m_modules_mutex);
+ Mutex::Locker lhs_locker(m_modules_mutex);
+ m_modules = rhs.m_modules;
+ }
}
return *this;
}
@@ -832,13 +856,15 @@ ModuleList::GetIndexForModule (const Module *module) const
static ModuleList &
GetSharedModuleList ()
{
- // NOTE: Intentionally leak the module list so a program doesn't have to
- // cleanup all modules and object files as it exits. This just wastes time
- // doing a bunch of cleanup that isn't required.
static ModuleList *g_shared_module_list = NULL;
- if (g_shared_module_list == NULL)
- g_shared_module_list = new ModuleList(); // <--- Intentional leak!!!
-
+ static std::once_flag g_once_flag;
+ std::call_once(g_once_flag, [](){
+ // NOTE: Intentionally leak the module list so a program doesn't have to
+ // cleanup all modules and object files as it exits. This just wastes time
+ // doing a bunch of cleanup that isn't required.
+ if (g_shared_module_list == NULL)
+ g_shared_module_list = new ModuleList(); // <--- Intentional leak!!!
+ });
return *g_shared_module_list;
}
@@ -905,7 +931,7 @@ ModuleList::GetSharedModule
for (size_t module_idx = 0; module_idx < num_matching_modules; ++module_idx)
{
module_sp = matching_module_list.GetModuleAtIndex(module_idx);
-
+
// Make sure the file for the module hasn't been modified
if (module_sp->FileHasChanged())
{
@@ -914,7 +940,8 @@ ModuleList::GetSharedModule
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_MODULES));
if (log)
- log->Printf("module changed: %p, removing from global module list", module_sp.get());
+ log->Printf("module changed: %p, removing from global module list",
+ static_cast<void*>(module_sp.get()));
shared_module_list.Remove (module_sp);
module_sp.reset();
@@ -949,7 +976,7 @@ ModuleList::GetSharedModule
{
if (did_create_ptr)
*did_create_ptr = true;
-
+
shared_module_list.ReplaceEquivalent(module_sp);
return error;
}
@@ -976,6 +1003,7 @@ ModuleList::GetSharedModule
file_spec.GetPath(path, sizeof(path));
if (path[0] == '\0')
module_file_spec.GetPath(path, sizeof(path));
+ // How can this check ever be true? This branch it is false, and we haven't modified file_spec.
if (file_spec.Exists())
{
std::string uuid_str;
@@ -1105,9 +1133,10 @@ ModuleList::LoadScriptingResourcesInTarget (Target *target,
module->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
error.AsCString());
errors.push_back(error);
+
+ if (!continue_on_error)
+ return false;
}
- if (!continue_on_error)
- return false;
}
}
}
diff --git a/source/Core/Opcode.cpp b/source/Core/Opcode.cpp
index 2bf7f5eae9b0..73f5f85923c6 100644
--- a/source/Core/Opcode.cpp
+++ b/source/Core/Opcode.cpp
@@ -63,7 +63,7 @@ Opcode::Dump (Stream *s, uint32_t min_byte_width)
// Add spaces to make sure bytes dispay comes out even in case opcodes
// aren't all the same size
- if (bytes_written < min_byte_width)
+ if (static_cast<uint32_t>(bytes_written) < min_byte_width)
bytes_written = s->Printf ("%*s", min_byte_width - bytes_written, "");
return bytes_written;
}
diff --git a/source/Core/PluginManager.cpp b/source/Core/PluginManager.cpp
index 813cec227525..cda55802fab8 100644
--- a/source/Core/PluginManager.cpp
+++ b/source/Core/PluginManager.cpp
@@ -20,10 +20,12 @@
#include "lldb/Core/Error.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DynamicLibrary.h"
using namespace lldb;
using namespace lldb_private;
@@ -41,7 +43,12 @@ typedef void (*PluginTermCallback) (void);
struct PluginInfo
{
- void *plugin_handle;
+ PluginInfo()
+ : plugin_init_callback(nullptr), plugin_term_callback(nullptr)
+ {
+ }
+
+ llvm::sys::DynamicLibrary library;
PluginInitCallback plugin_init_callback;
PluginTermCallback plugin_term_callback;
};
@@ -79,6 +86,12 @@ SetPluginInfo (const FileSpec &plugin_file_spec, const PluginInfo &plugin_info)
plugin_map[plugin_file_spec] = plugin_info;
}
+template <typename FPtrTy>
+static FPtrTy
+CastToFPtr (void *VPtr)
+{
+ return reinterpret_cast<FPtrTy>(reinterpret_cast<intptr_t>(VPtr));
+}
static FileSpec::EnumerateDirectoryResult
LoadPluginCallback
@@ -106,16 +119,15 @@ LoadPluginCallback
return FileSpec::eEnumerateDirectoryResultNext;
else
{
- PluginInfo plugin_info = { NULL, NULL, NULL };
- uint32_t flags = Host::eDynamicLibraryOpenOptionLazy |
- Host::eDynamicLibraryOpenOptionLocal |
- Host::eDynamicLibraryOpenOptionLimitGetSymbol;
+ PluginInfo plugin_info;
- plugin_info.plugin_handle = Host::DynamicLibraryOpen (plugin_file_spec, flags, error);
- if (plugin_info.plugin_handle)
+ std::string pluginLoadError;
+ plugin_info.library = llvm::sys::DynamicLibrary::getPermanentLibrary (plugin_file_spec.GetPath().c_str(), &pluginLoadError);
+ if (plugin_info.library.isValid())
{
bool success = false;
- plugin_info.plugin_init_callback = (PluginInitCallback)Host::DynamicLibraryGetSymbol (plugin_info.plugin_handle, "LLDBPluginInitialize", error);
+ plugin_info.plugin_init_callback =
+ CastToFPtr<PluginInitCallback>(plugin_info.library.getAddressOfSymbol("LLDBPluginInitialize"));
if (plugin_info.plugin_init_callback)
{
// Call the plug-in "bool LLDBPluginInitialize(void)" function
@@ -125,16 +137,15 @@ LoadPluginCallback
if (success)
{
// It is ok for the "LLDBPluginTerminate" symbol to be NULL
- plugin_info.plugin_term_callback = (PluginTermCallback)Host::DynamicLibraryGetSymbol (plugin_info.plugin_handle, "LLDBPluginTerminate", error);
+ plugin_info.plugin_term_callback =
+ CastToFPtr<PluginTermCallback>(plugin_info.library.getAddressOfSymbol("LLDBPluginTerminate"));
}
else
{
- // The initialize function returned FALSE which means the
- // plug-in might not be compatible, or might be too new or
- // too old, or might not want to run on this machine.
- Host::DynamicLibraryClose (plugin_info.plugin_handle);
- plugin_info.plugin_handle = NULL;
- plugin_info.plugin_init_callback = NULL;
+ // The initialize function returned FALSE which means the plug-in might not be
+ // compatible, or might be too new or too old, or might not want to run on this
+ // machine. Set it to a default-constructed instance to invalidate it.
+ plugin_info = PluginInfo();
}
// Regardless of success or failure, cache the plug-in load
@@ -153,7 +164,7 @@ LoadPluginCallback
{
// Try and recurse into anything that a directory or symbolic link.
// We must also do this for unknown as sometimes the directory enumeration
- // might be enurating a file system that doesn't have correct file type
+ // might be enumerating a file system that doesn't have correct file type
// information.
return FileSpec::eEnumerateDirectoryResultEnter;
}
@@ -171,7 +182,7 @@ PluginManager::Initialize ()
const bool find_files = true;
const bool find_other = true;
char dir_path[PATH_MAX];
- if (Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec))
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec))
{
if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path)))
{
@@ -184,7 +195,7 @@ PluginManager::Initialize ()
}
}
- if (Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec))
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec))
{
if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path)))
{
@@ -210,11 +221,10 @@ PluginManager::Terminate ()
{
// Call the plug-in "void LLDBPluginTerminate (void)" function if there
// is one (if the symbol was not NULL).
- if (pos->second.plugin_handle)
+ if (pos->second.library.isValid())
{
if (pos->second.plugin_term_callback)
pos->second.plugin_term_callback();
- Host::DynamicLibraryClose (pos->second.plugin_handle);
}
}
plugin_map.clear();
@@ -544,6 +554,116 @@ PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const ConstString &n
return NULL;
}
+#pragma mark JITLoader
+
+
+struct JITLoaderInstance
+{
+ JITLoaderInstance() :
+ name(),
+ description(),
+ create_callback(NULL),
+ debugger_init_callback (NULL)
+ {
+ }
+
+ ConstString name;
+ std::string description;
+ JITLoaderCreateInstance create_callback;
+ DebuggerInitializeCallback debugger_init_callback;
+};
+
+typedef std::vector<JITLoaderInstance> JITLoaderInstances;
+
+
+static Mutex &
+GetJITLoaderMutex ()
+{
+ static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
+ return g_instances_mutex;
+}
+
+static JITLoaderInstances &
+GetJITLoaderInstances ()
+{
+ static JITLoaderInstances g_instances;
+ return g_instances;
+}
+
+
+bool
+PluginManager::RegisterPlugin
+(
+ const ConstString &name,
+ const char *description,
+ JITLoaderCreateInstance create_callback,
+ DebuggerInitializeCallback debugger_init_callback
+)
+{
+ if (create_callback)
+ {
+ JITLoaderInstance instance;
+ assert ((bool)name);
+ instance.name = name;
+ if (description && description[0])
+ instance.description = description;
+ instance.create_callback = create_callback;
+ instance.debugger_init_callback = debugger_init_callback;
+ Mutex::Locker locker (GetJITLoaderMutex ());
+ GetJITLoaderInstances ().push_back (instance);
+ }
+ return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (JITLoaderCreateInstance create_callback)
+{
+ if (create_callback)
+ {
+ Mutex::Locker locker (GetJITLoaderMutex ());
+ JITLoaderInstances &instances = GetJITLoaderInstances ();
+
+ JITLoaderInstances::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;
+}
+
+JITLoaderCreateInstance
+PluginManager::GetJITLoaderCreateCallbackAtIndex (uint32_t idx)
+{
+ Mutex::Locker locker (GetJITLoaderMutex ());
+ JITLoaderInstances &instances = GetJITLoaderInstances ();
+ if (idx < instances.size())
+ return instances[idx].create_callback;
+ return NULL;
+}
+
+JITLoaderCreateInstance
+PluginManager::GetJITLoaderCreateCallbackForPluginName (const ConstString &name)
+{
+ if (name)
+ {
+ Mutex::Locker locker (GetJITLoaderMutex ());
+ JITLoaderInstances &instances = GetJITLoaderInstances ();
+
+ JITLoaderInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (name == pos->name)
+ return pos->create_callback;
+ }
+ }
+ return NULL;
+}
+
#pragma mark EmulateInstruction
@@ -968,7 +1088,8 @@ struct ObjectFileInstance
description(),
create_callback(NULL),
create_memory_callback (NULL),
- get_module_specifications (NULL)
+ get_module_specifications (NULL),
+ save_core (NULL)
{
}
@@ -977,6 +1098,7 @@ struct ObjectFileInstance
ObjectFileCreateInstance create_callback;
ObjectFileCreateMemoryInstance create_memory_callback;
ObjectFileGetModuleSpecifications get_module_specifications;
+ ObjectFileSaveCore save_core;
};
typedef std::vector<ObjectFileInstance> ObjectFileInstances;
@@ -1001,7 +1123,8 @@ PluginManager::RegisterPlugin (const ConstString &name,
const char *description,
ObjectFileCreateInstance create_callback,
ObjectFileCreateMemoryInstance create_memory_callback,
- ObjectFileGetModuleSpecifications get_module_specifications)
+ ObjectFileGetModuleSpecifications get_module_specifications,
+ ObjectFileSaveCore save_core)
{
if (create_callback)
{
@@ -1012,6 +1135,7 @@ PluginManager::RegisterPlugin (const ConstString &name,
instance.description = description;
instance.create_callback = create_callback;
instance.create_memory_callback = create_memory_callback;
+ instance.save_core = save_core;
instance.get_module_specifications = get_module_specifications;
Mutex::Locker locker (GetObjectFileMutex ());
GetObjectFileInstances ().push_back (instance);
@@ -1108,7 +1232,22 @@ PluginManager::GetObjectFileCreateMemoryCallbackForPluginName (const ConstString
return NULL;
}
-
+Error
+PluginManager::SaveCore (const lldb::ProcessSP &process_sp, const FileSpec &outfile)
+{
+ Error error;
+ Mutex::Locker locker (GetObjectFileMutex ());
+ ObjectFileInstances &instances = GetObjectFileInstances ();
+
+ ObjectFileInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (pos->save_core && pos->save_core (process_sp, outfile, error))
+ return error;
+ }
+ error.SetErrorString("no ObjectFile plugins were able to save a core for this process");
+ return error;
+}
#pragma mark ObjectContainer
@@ -1945,6 +2084,19 @@ PluginManager::DebuggerInitialize (Debugger &debugger)
}
}
+ // Initialize the JITLoader plugins
+ {
+ Mutex::Locker locker (GetJITLoaderMutex ());
+ JITLoaderInstances &instances = GetJITLoaderInstances ();
+
+ JITLoaderInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (pos->debugger_init_callback)
+ pos->debugger_init_callback (debugger);
+ }
+ }
+
// Initialize the Platform plugins
{
Mutex::Locker locker (GetPlatformInstancesMutex ());
diff --git a/source/Core/RegularExpression.cpp b/source/Core/RegularExpression.cpp
index 4ccd7748b13e..88415f616828 100644
--- a/source/Core/RegularExpression.cpp
+++ b/source/Core/RegularExpression.cpp
@@ -71,7 +71,7 @@ RegularExpression::operator= (const RegularExpression &rhs)
//----------------------------------------------------------------------
// Destructor
//
-// Any previosuly compiled regular expression contained in this
+// Any previously compiled regular expression contained in this
// object will be freed.
//----------------------------------------------------------------------
RegularExpression::~RegularExpression()
@@ -81,14 +81,14 @@ RegularExpression::~RegularExpression()
//----------------------------------------------------------------------
// Compile a regular expression using the supplied regular
-// expression text and flags. The compied regular expression lives
+// expression text and flags. The compiled regular expression lives
// in this object so that it can be readily used for regular
// expression matches. Execute() can be called after the regular
-// expression is compiled. Any previosuly compiled regular
+// expression is compiled. Any previously compiled regular
// expression contained in this object will be freed.
//
// RETURNS
-// True of the refular expression compiles successfully, false
+// True if the regular expression compiles successfully, false
// otherwise.
//----------------------------------------------------------------------
bool
diff --git a/source/Core/Scalar.cpp b/source/Core/Scalar.cpp
index 26f743796254..1bfe6f2f1baf 100644
--- a/source/Core/Scalar.cpp
+++ b/source/Core/Scalar.cpp
@@ -62,7 +62,7 @@ PromoteToMaxType
promoted_lhs_ptr = &temp_value; // Update the pointer for the promoted left hand side
}
- // Make sure our type promotion worked as exptected
+ // Make sure our type promotion worked as expected
if (promoted_lhs_ptr->GetType() == promoted_rhs_ptr->GetType())
return promoted_lhs_ptr->GetType(); // Return the resulting max type
@@ -1794,7 +1794,7 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by
if (!success)
error.SetErrorStringWithFormat ("'%s' is not a valid unsigned integer string value", value_str);
else if (!UIntValueIsValidForSize (uval64, byte_size))
- error.SetErrorStringWithFormat ("value 0x%" PRIx64 " is too large to fit in a %zu byte unsigned integer value", uval64, byte_size);
+ error.SetErrorStringWithFormat("value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value", uval64, (uint64_t)byte_size);
else
{
m_type = Scalar::GetValueTypeForUnsignedIntegerWithByteSize (byte_size);
@@ -1804,14 +1804,14 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by
case e_ulong: m_data.ulong = (ulong_t)uval64; break;
case e_ulonglong: m_data.ulonglong = (ulonglong_t)uval64; break;
default:
- error.SetErrorStringWithFormat ("unsupported unsigned integer byte size: %zu", byte_size);
+ error.SetErrorStringWithFormat("unsupported unsigned integer byte size: %" PRIu64 "", (uint64_t)byte_size);
break;
}
}
}
else
{
- error.SetErrorStringWithFormat ("unsupported unsigned integer byte size: %zu", byte_size);
+ error.SetErrorStringWithFormat("unsupported unsigned integer byte size: %" PRIu64 "", (uint64_t)byte_size);
return error;
}
break;
@@ -1823,7 +1823,7 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by
if (!success)
error.SetErrorStringWithFormat ("'%s' is not a valid signed integer string value", value_str);
else if (!SIntValueIsValidForSize (sval64, byte_size))
- error.SetErrorStringWithFormat ("value 0x%" PRIx64 " is too large to fit in a %zu byte signed integer value", sval64, byte_size);
+ error.SetErrorStringWithFormat("value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte signed integer value", sval64, (uint64_t)byte_size);
else
{
m_type = Scalar::GetValueTypeForSignedIntegerWithByteSize (byte_size);
@@ -1833,14 +1833,14 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by
case e_slong: m_data.slong = (slong_t)sval64; break;
case e_slonglong: m_data.slonglong = (slonglong_t)sval64; break;
default:
- error.SetErrorStringWithFormat ("unsupported signed integer byte size: %zu", byte_size);
+ error.SetErrorStringWithFormat("unsupported signed integer byte size: %" PRIu64 "", (uint64_t)byte_size);
break;
}
}
}
else
{
- error.SetErrorStringWithFormat ("unsupported signed integer byte size: %zu", byte_size);
+ error.SetErrorStringWithFormat("unsupported signed integer byte size: %" PRIu64 "", (uint64_t)byte_size);
return error;
}
break;
@@ -1869,7 +1869,7 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by
}
else
{
- error.SetErrorStringWithFormat ("unsupported float byte size: %zu", byte_size);
+ error.SetErrorStringWithFormat("unsupported float byte size: %" PRIu64 "", (uint64_t)byte_size);
return error;
}
break;
@@ -1908,7 +1908,7 @@ Scalar::SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t b
case 4: operator=((uint32_t)data.GetU32(&offset)); break;
case 8: operator=((uint64_t)data.GetU64(&offset)); break;
default:
- error.SetErrorStringWithFormat ("unsupported unsigned integer byte size: %zu", byte_size);
+ error.SetErrorStringWithFormat("unsupported unsigned integer byte size: %" PRIu64 "", (uint64_t)byte_size);
break;
}
}
@@ -1924,7 +1924,7 @@ Scalar::SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t b
case 4: operator=((int32_t)data.GetU32(&offset)); break;
case 8: operator=((int64_t)data.GetU64(&offset)); break;
default:
- error.SetErrorStringWithFormat ("unsupported signed integer byte size: %zu", byte_size);
+ error.SetErrorStringWithFormat("unsupported signed integer byte size: %" PRIu64 "", (uint64_t)byte_size);
break;
}
}
@@ -1940,7 +1940,7 @@ Scalar::SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t b
else if (byte_size == sizeof (long double))
operator=((long double)data.GetLongDouble(&offset));
else
- error.SetErrorStringWithFormat ("unsupported float byte size: %zu", byte_size);
+ error.SetErrorStringWithFormat("unsupported float byte size: %" PRIu64 "", (uint64_t)byte_size);
}
break;
}
diff --git a/source/Core/SearchFilter.cpp b/source/Core/SearchFilter.cpp
index 64b5a838d3de..dee2f2e4bd5e 100644
--- a/source/Core/SearchFilter.cpp
+++ b/source/Core/SearchFilter.cpp
@@ -592,7 +592,7 @@ SearchFilterByModuleList::GetDescription (Stream *s)
}
else
{
- s->Printf (", modules(%zu) = ", num_modules);
+ s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules);
for (size_t i = 0; i < num_modules; i++)
{
if (s->GetVerbose())
diff --git a/source/Core/Section.cpp b/source/Core/Section.cpp
index 28d7d93b9bb9..3267c1866221 100644
--- a/source/Core/Section.cpp
+++ b/source/Core/Section.cpp
@@ -13,6 +13,8 @@
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
+#include <limits>
+
using namespace lldb;
using namespace lldb_private;
@@ -25,6 +27,7 @@ Section::Section (const ModuleSP &module_sp,
addr_t byte_size,
lldb::offset_t file_offset,
lldb::offset_t file_size,
+ uint32_t log2align,
uint32_t flags) :
ModuleChild (module_sp),
UserID (sect_id),
@@ -37,6 +40,7 @@ Section::Section (const ModuleSP &module_sp,
m_byte_size (byte_size),
m_file_offset (file_offset),
m_file_size (file_size),
+ m_log2align (log2align),
m_children (),
m_fake (false),
m_encrypted (false),
@@ -56,6 +60,7 @@ Section::Section (const lldb::SectionSP &parent_section_sp,
addr_t byte_size,
lldb::offset_t file_offset,
lldb::offset_t file_size,
+ uint32_t log2align,
uint32_t flags) :
ModuleChild (module_sp),
UserID (sect_id),
@@ -68,6 +73,7 @@ Section::Section (const lldb::SectionSP &parent_section_sp,
m_byte_size (byte_size),
m_file_offset (file_offset),
m_file_size (file_size),
+ m_log2align (log2align),
m_children (),
m_fake (false),
m_encrypted (false),
@@ -140,7 +146,7 @@ Section::GetLoadBaseAddress (Target *target) const
if (load_base_addr != LLDB_INVALID_ADDRESS)
load_base_addr += GetOffset();
}
- else
+ if (load_base_addr == LLDB_INVALID_ADDRESS)
{
load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress (const_cast<Section *>(this)->shared_from_this());
}
@@ -331,10 +337,14 @@ SectionList::operator = (const SectionList& rhs)
size_t
SectionList::AddSection (const lldb::SectionSP& section_sp)
{
- assert (section_sp.get());
- size_t section_index = m_sections.size();
- m_sections.push_back(section_sp);
- return section_index;
+ if (section_sp)
+ {
+ size_t section_index = m_sections.size();
+ m_sections.push_back(section_sp);
+ return section_index;
+ }
+
+ return std::numeric_limits<size_t>::max ();
}
// Warning, this can be slow as it's removing items from a std::vector.
@@ -433,14 +443,16 @@ SectionList::FindSectionByName (const ConstString &section_dstr) const
for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
{
Section *child_section = sect_iter->get();
- assert (child_section);
- if (child_section->GetName() == section_dstr)
- {
- sect_sp = *sect_iter;
- }
- else
+ if (child_section)
{
- sect_sp = child_section->GetChildren().FindSectionByName(section_dstr);
+ if (child_section->GetName() == section_dstr)
+ {
+ sect_sp = *sect_iter;
+ }
+ else
+ {
+ sect_sp = child_section->GetChildren().FindSectionByName(section_dstr);
+ }
}
}
}
diff --git a/source/Core/SourceManager.cpp b/source/Core/SourceManager.cpp
index 0a6a80401d8d..44ab50197c19 100644
--- a/source/Core/SourceManager.cpp
+++ b/source/Core/SourceManager.cpp
@@ -373,7 +373,7 @@ SourceManager::File::File(const FileSpec &file_spec, Target *target) :
{
if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit))
got_multiple = true;
- break;
+ break;
}
else
test_cu_spec = sc.comp_unit;
diff --git a/source/Core/Stream.cpp b/source/Core/Stream.cpp
index 49c15d63c361..29bebb3ae3db 100644
--- a/source/Core/Stream.cpp
+++ b/source/Core/Stream.cpp
@@ -252,7 +252,7 @@ Stream::EOL()
//------------------------------------------------------------------
// Indent the current line using the current indentation level and
-// print an optional string following the idenatation spaces.
+// print an optional string following the indentation spaces.
//------------------------------------------------------------------
size_t
Stream::Indent(const char *s)
@@ -479,7 +479,7 @@ Stream::PrintfAsRawHex8 (const char *format, ...)
va_list args;
va_list args_copy;
va_start (args, format);
- va_copy (args, args_copy); // Copy this so we
+ va_copy (args_copy,args); // Copy this so we
char str[1024];
size_t bytes_written = 0;
diff --git a/source/Core/StructuredData.cpp b/source/Core/StructuredData.cpp
new file mode 100644
index 000000000000..3c43e41f3c94
--- /dev/null
+++ b/source/Core/StructuredData.cpp
@@ -0,0 +1,429 @@
+//===---------------------StructuredData.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/StructuredData.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+using namespace lldb_private;
+
+
+static StructuredData::ObjectSP read_json_object (const char **ch);
+static StructuredData::ObjectSP read_json_array (const char **ch);
+
+static StructuredData::ObjectSP
+read_json_number (const char **ch)
+{
+ StructuredData::ObjectSP object_sp;
+ while (isspace (**ch))
+ (*ch)++;
+ const char *start_of_number = *ch;
+ bool is_integer = true;
+ bool is_float = false;
+ while (isdigit(**ch) || **ch == '-' || **ch == '.' || **ch == '+' || **ch == 'e' || **ch == 'E')
+ {
+ if (isdigit(**ch) == false && **ch != '-')
+ {
+ is_integer = false;
+ is_float = true;
+ }
+ (*ch)++;
+ }
+ while (isspace (**ch))
+ (*ch)++;
+ if (**ch == ',' || **ch == ']' || **ch == '}')
+ {
+ if (is_integer)
+ {
+ errno = 0;
+ uint64_t val = strtoul (start_of_number, NULL, 10);
+ if (errno == 0)
+ {
+ object_sp.reset(new StructuredData::Integer());
+ object_sp->GetAsInteger()->SetValue (val);
+ }
+ }
+ if (is_float)
+ {
+ char *end_of_number = NULL;
+ errno = 0;
+ double val = strtod (start_of_number, &end_of_number);
+ if (errno == 0 && end_of_number != start_of_number && end_of_number != NULL)
+ {
+ object_sp.reset(new StructuredData::Float());
+ object_sp->GetAsFloat()->SetValue (val);
+ }
+ }
+ }
+ return object_sp;
+}
+
+static std::string
+read_json_string (const char **ch)
+{
+ std::string string;
+ if (**ch == '"')
+ {
+ (*ch)++;
+ while (**ch != '\0')
+ {
+ if (**ch == '"')
+ {
+ (*ch)++;
+ while (isspace (**ch))
+ (*ch)++;
+ break;
+ }
+ else if (**ch == '\\')
+ {
+ switch (**ch)
+ {
+ case '"':
+ string.push_back('"');
+ *ch += 2;
+ break;
+ case '\\':
+ string.push_back('\\');
+ *ch += 2;
+ break;
+ case '/':
+ string.push_back('/');
+ *ch += 2;
+ break;
+ case 'b':
+ string.push_back('\b');
+ *ch += 2;
+ break;
+ case 'f':
+ string.push_back('\f');
+ *ch += 2;
+ break;
+ case 'n':
+ string.push_back('\n');
+ *ch += 2;
+ break;
+ case 'r':
+ string.push_back('\r');
+ *ch += 2;
+ break;
+ case 't':
+ string.push_back('\t');
+ *ch += 2;
+ break;
+ case 'u':
+ // FIXME handle four-hex-digits
+ *ch += 10;
+ break;
+ default:
+ *ch += 1;
+ }
+ }
+ else
+ {
+ string.push_back (**ch);
+ }
+ (*ch)++;
+ }
+ }
+ return string;
+}
+
+static StructuredData::ObjectSP
+read_json_value (const char **ch)
+{
+ StructuredData::ObjectSP object_sp;
+ while (isspace (**ch))
+ (*ch)++;
+
+ if (**ch == '{')
+ {
+ object_sp = read_json_object (ch);
+ }
+ else if (**ch == '[')
+ {
+ object_sp = read_json_array (ch);
+ }
+ else if (**ch == '"')
+ {
+ std::string string = read_json_string (ch);
+ object_sp.reset(new StructuredData::String());
+ object_sp->GetAsString()->SetValue(string);
+ }
+ else
+ {
+ if (strncmp (*ch, "true", 4) == 0)
+ {
+ object_sp.reset(new StructuredData::Boolean());
+ object_sp->GetAsBoolean()->SetValue(true);
+ *ch += 4;
+ }
+ else if (strncmp (*ch, "false", 5) == 0)
+ {
+ object_sp.reset(new StructuredData::Boolean());
+ object_sp->GetAsBoolean()->SetValue(false);
+ *ch += 5;
+ }
+ else if (strncmp (*ch, "null", 4) == 0)
+ {
+ object_sp.reset(new StructuredData::Null());
+ *ch += 4;
+ }
+ else
+ {
+ object_sp = read_json_number (ch);
+ }
+ }
+ return object_sp;
+}
+
+static StructuredData::ObjectSP
+read_json_array (const char **ch)
+{
+ StructuredData::ObjectSP object_sp;
+ if (**ch == '[')
+ {
+ (*ch)++;
+ while (isspace (**ch))
+ (*ch)++;
+
+ bool first_value = true;
+ while (**ch != '\0' && (first_value || **ch == ','))
+ {
+ if (**ch == ',')
+ (*ch)++;
+ first_value = false;
+ while (isspace (**ch))
+ (*ch)++;
+ lldb_private::StructuredData::ObjectSP value_sp = read_json_value (ch);
+ if (value_sp)
+ {
+ if (object_sp.get() == NULL)
+ {
+ object_sp.reset(new StructuredData::Array());
+ }
+ object_sp->GetAsArray()->Push (value_sp);
+ }
+ while (isspace (**ch))
+ (*ch)++;
+ }
+ if (**ch == ']')
+ {
+ // FIXME should throw an error if we don't see a } to close out the JSON object
+ (*ch)++;
+ while (isspace (**ch))
+ (*ch)++;
+ }
+ }
+ return object_sp;
+}
+
+static StructuredData::ObjectSP
+read_json_object (const char **ch)
+{
+ StructuredData::ObjectSP object_sp;
+ if (**ch == '{')
+ {
+ (*ch)++;
+ while (isspace (**ch))
+ (*ch)++;
+ bool first_pair = true;
+ while (**ch != '\0' && (first_pair || **ch == ','))
+ {
+ first_pair = false;
+ if (**ch == ',')
+ (*ch)++;
+ while (isspace (**ch))
+ (*ch)++;
+ if (**ch != '"')
+ break;
+ std::string key_string = read_json_string (ch);
+ while (isspace (**ch))
+ (*ch)++;
+ if (key_string.size() > 0 && **ch == ':')
+ {
+ (*ch)++;
+ while (isspace (**ch))
+ (*ch)++;
+ lldb_private::StructuredData::ObjectSP value_sp = read_json_value (ch);
+ if (value_sp.get())
+ {
+ if (object_sp.get() == NULL)
+ {
+ object_sp.reset(new StructuredData::Dictionary());
+ }
+ object_sp->GetAsDictionary()->AddItem (key_string.c_str(), value_sp);
+ }
+ }
+ while (isspace (**ch))
+ (*ch)++;
+ }
+ if (**ch == '}')
+ {
+ // FIXME should throw an error if we don't see a } to close out the JSON object
+ (*ch)++;
+ while (isspace (**ch))
+ (*ch)++;
+ }
+ }
+ return object_sp;
+}
+
+
+StructuredData::ObjectSP
+StructuredData::ParseJSON (std::string json_text)
+{
+ StructuredData::ObjectSP object_sp;
+ const size_t json_text_size = json_text.size();
+ if (json_text_size > 0)
+ {
+ const char *start_of_json_text = json_text.c_str();
+ const char *c = json_text.c_str();
+ while (*c != '\0' &&
+ static_cast<size_t>(c - start_of_json_text) <= json_text_size)
+ {
+ while (isspace (*c) &&
+ static_cast<size_t>(c - start_of_json_text) < json_text_size)
+ c++;
+ if (*c == '{')
+ {
+ object_sp = read_json_object (&c);
+ }
+ else
+ {
+ // We have bad characters here, this is likely an illegal JSON string.
+ return object_sp;
+ }
+ }
+ }
+ return object_sp;
+}
+
+StructuredData::ObjectSP
+StructuredData::Object::GetObjectForDotSeparatedPath (llvm::StringRef path)
+{
+ if (this->GetType() == Type::eTypeDictionary)
+ {
+ std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.');
+ std::string key = match.first.str();
+ ObjectSP value = this->GetAsDictionary()->GetValueForKey (key.c_str());
+ if (value.get())
+ {
+ // Do we have additional words to descend? If not, return the
+ // value we're at right now.
+ if (match.second.empty())
+ {
+ return value;
+ }
+ else
+ {
+ return value->GetObjectForDotSeparatedPath (match.second);
+ }
+ }
+ return ObjectSP();
+ }
+
+ if (this->GetType() == Type::eTypeArray)
+ {
+ std::pair<llvm::StringRef, llvm::StringRef> match = path.split('[');
+ if (match.second.size() == 0)
+ {
+ return this->shared_from_this();
+ }
+ errno = 0;
+ uint64_t val = strtoul (match.second.str().c_str(), NULL, 10);
+ if (errno == 0)
+ {
+ return this->GetAsArray()->GetItemAtIndex(val);
+ }
+ return ObjectSP();
+ }
+
+ return this->shared_from_this();
+}
+
+void
+StructuredData::Array::Dump (Stream &s) const
+{
+ s << "[";
+ const size_t arrsize = m_items.size();
+ for (size_t i = 0; i < arrsize; ++i)
+ {
+ m_items[i]->Dump(s);
+ if (i + 1 < arrsize)
+ s << ",";
+ }
+ s << "]";
+}
+
+void
+StructuredData::Integer::Dump (Stream &s) const
+{
+ s.Printf ("%" PRIu64, m_value);
+}
+
+
+void
+StructuredData::Float::Dump (Stream &s) const
+{
+ s.Printf ("%lf", m_value);
+}
+
+void
+StructuredData::Boolean::Dump (Stream &s) const
+{
+ if (m_value == true)
+ s.PutCString ("true");
+ else
+ s.PutCString ("false");
+}
+
+
+void
+StructuredData::String::Dump (Stream &s) const
+{
+ std::string quoted;
+ const size_t strsize = m_value.size();
+ for (size_t i = 0; i < strsize ; ++i)
+ {
+ char ch = m_value[i];
+ if (ch == '"')
+ quoted.push_back ('\\');
+ quoted.push_back (ch);
+ }
+ s.Printf ("\"%s\"", quoted.c_str());
+}
+
+void
+StructuredData::Dictionary::Dump (Stream &s) const
+{
+ bool have_printed_one_elem = false;
+ s << "{";
+ for (collection::const_iterator iter = m_dict.begin(); iter != m_dict.end(); ++iter)
+ {
+ if (have_printed_one_elem == false)
+ {
+ have_printed_one_elem = true;
+ }
+ else
+ {
+ s << ",";
+ }
+ s << "\"" << iter->first.AsCString() << "\":";
+ iter->second->Dump(s);
+ }
+ s << "}";
+}
+
+void
+StructuredData::Null::Dump (Stream &s) const
+{
+ s << "null";
+}
diff --git a/source/Core/Value.cpp b/source/Core/Value.cpp
index 9d42a3774624..db33fce4a03e 100644
--- a/source/Core/Value.cpp
+++ b/source/Core/Value.cpp
@@ -55,7 +55,7 @@ Value::Value(const Scalar& scalar) :
}
-Value::Value(const uint8_t *bytes, int len) :
+Value::Value(const void *bytes, int len) :
m_value (),
m_vector (),
m_clang_type (),
@@ -64,8 +64,7 @@ Value::Value(const uint8_t *bytes, int len) :
m_context_type (eContextTypeInvalid),
m_data_buffer ()
{
- m_data_buffer.CopyData(bytes, len);
- m_value = (uintptr_t)m_data_buffer.GetBytes();
+ SetBytes(bytes, len);
}
Value::Value(const Value &v) :
@@ -77,7 +76,8 @@ Value::Value(const Value &v) :
m_context_type (v.m_context_type),
m_data_buffer ()
{
- if ((uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS) == (uintptr_t)v.m_data_buffer.GetBytes())
+ const uintptr_t rhs_value = (uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS);
+ if ((rhs_value != 0) && (rhs_value == (uintptr_t)v.m_data_buffer.GetBytes()))
{
m_data_buffer.CopyData(v.m_data_buffer.GetBytes(),
v.m_data_buffer.GetByteSize());
@@ -97,7 +97,8 @@ Value::operator=(const Value &rhs)
m_context = rhs.m_context;
m_value_type = rhs.m_value_type;
m_context_type = rhs.m_context_type;
- if ((uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS) == (uintptr_t)rhs.m_data_buffer.GetBytes())
+ const uintptr_t rhs_value = (uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS);
+ if ((rhs_value != 0) && (rhs_value == (uintptr_t)rhs.m_data_buffer.GetBytes()))
{
m_data_buffer.CopyData(rhs.m_data_buffer.GetBytes(),
rhs.m_data_buffer.GetByteSize());
@@ -109,6 +110,22 @@ Value::operator=(const Value &rhs)
}
void
+Value::SetBytes (const void *bytes, int len)
+{
+ m_value_type = eValueTypeHostAddress;
+ m_data_buffer.CopyData(bytes, len);
+ m_value = (uintptr_t)m_data_buffer.GetBytes();
+}
+
+void
+Value::AppendBytes (const void *bytes, int len)
+{
+ m_value_type = eValueTypeHostAddress;
+ m_data_buffer.AppendData (bytes, len);
+ m_value = (uintptr_t)m_data_buffer.GetBytes();
+}
+
+void
Value::Dump (Stream* strm)
{
m_value.GetValue (strm, true);
@@ -155,12 +172,74 @@ Value::GetType()
return NULL;
}
-void
+size_t
+Value::AppendDataToHostBuffer (const Value &rhs)
+{
+ size_t curr_size = m_data_buffer.GetByteSize();
+ Error error;
+ switch (rhs.GetValueType())
+ {
+ case eValueTypeScalar:
+ {
+ const size_t scalar_size = rhs.m_value.GetByteSize();
+ if (scalar_size > 0)
+ {
+ const size_t new_size = curr_size + scalar_size;
+ if (ResizeData(new_size) == new_size)
+ {
+ rhs.m_value.GetAsMemoryData (m_data_buffer.GetBytes() + curr_size,
+ scalar_size,
+ lldb::endian::InlHostByteOrder(),
+ error);
+ return scalar_size;
+ }
+ }
+ }
+ break;
+ case eValueTypeVector:
+ {
+ const size_t vector_size = rhs.m_vector.length;
+ if (vector_size > 0)
+ {
+ const size_t new_size = curr_size + vector_size;
+ if (ResizeData(new_size) == new_size)
+ {
+ ::memcpy (m_data_buffer.GetBytes() + curr_size,
+ rhs.m_vector.bytes,
+ vector_size);
+ return vector_size;
+ }
+ }
+ }
+ break;
+ case eValueTypeFileAddress:
+ case eValueTypeLoadAddress:
+ case eValueTypeHostAddress:
+ {
+ const uint8_t *src = rhs.GetBuffer().GetBytes();
+ const size_t src_len = rhs.GetBuffer().GetByteSize();
+ if (src && src_len > 0)
+ {
+ const size_t new_size = curr_size + src_len;
+ if (ResizeData(new_size) == new_size)
+ {
+ ::memcpy (m_data_buffer.GetBytes() + curr_size, src, src_len);
+ return src_len;
+ }
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+size_t
Value::ResizeData(size_t len)
{
m_value_type = eValueTypeHostAddress;
m_data_buffer.SetByteSize(len);
m_value = (uintptr_t)m_data_buffer.GetBytes();
+ return m_data_buffer.GetByteSize();
}
bool
@@ -579,7 +658,12 @@ Value::GetValueAsData (ExecutionContext *exe_ctx,
{
if (address_type == eAddressTypeHost)
{
- // The address is an address in this process, so just copy it
+ // The address is an address in this process, so just copy it.
+ if (address == 0)
+ {
+ error.SetErrorStringWithFormat("trying to read from host address of 0.");
+ return error;
+ }
memcpy (dst, (uint8_t*)NULL + address, byte_size);
}
else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile))
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp
index 10e5ab452f0f..1819e834536a 100644
--- a/source/Core/ValueObject.cpp
+++ b/source/Core/ValueObject.cpp
@@ -237,28 +237,25 @@ ValueObject::UpdateFormatsIfNeeded()
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
if (log)
log->Printf("[%s %p] checking for FormatManager revisions. ValueObject rev: %d - Global rev: %d",
- GetName().GetCString(),
- this,
- m_last_format_mgr_revision,
- DataVisualization::GetCurrentRevision());
-
+ GetName().GetCString(), static_cast<void*>(this),
+ m_last_format_mgr_revision,
+ DataVisualization::GetCurrentRevision());
+
bool any_change = false;
-
+
if ( (m_last_format_mgr_revision != DataVisualization::GetCurrentRevision()))
{
+ m_last_format_mgr_revision = DataVisualization::GetCurrentRevision();
+ any_change = true;
+
SetValueFormat(DataVisualization::GetFormat (*this, eNoDynamicValues));
SetSummaryFormat(DataVisualization::GetSummaryFormat (*this, GetDynamicValueType()));
#ifndef LLDB_DISABLE_PYTHON
SetSyntheticChildren(DataVisualization::GetSyntheticChildren (*this, GetDynamicValueType()));
#endif
-
- m_last_format_mgr_revision = DataVisualization::GetCurrentRevision();
-
- any_change = true;
}
-
+
return any_change;
-
}
void
@@ -796,7 +793,6 @@ ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_
ExecutionContext exe_ctx (GetExecutionContextRef());
child_clang_type = GetClangType().GetChildClangTypeAtIndex (&exe_ctx,
- GetName().GetCString(),
idx,
transparent_pointers,
omit_empty_base_classes,
@@ -807,7 +803,8 @@ ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_
child_bitfield_bit_size,
child_bitfield_bit_offset,
child_is_base_class,
- child_is_deref_of_parent);
+ child_is_deref_of_parent,
+ this);
if (child_clang_type)
{
if (synthetic_index)
@@ -978,14 +975,15 @@ ValueObject::GetPointeeData (DataExtractor& data,
ValueObjectSP pointee_sp = Dereference(error);
if (error.Fail() || pointee_sp.get() == NULL)
return 0;
- return pointee_sp->GetData(data);
+ return pointee_sp->GetData(data, error);
}
else
{
ValueObjectSP child_sp = GetChildAtIndex(0, true);
if (child_sp.get() == NULL)
return 0;
- return child_sp->GetData(data);
+ Error error;
+ return child_sp->GetData(data, error);
}
return true;
}
@@ -1059,11 +1057,11 @@ ValueObject::GetPointeeData (DataExtractor& data,
}
uint64_t
-ValueObject::GetData (DataExtractor& data)
+ValueObject::GetData (DataExtractor& data, Error &error)
{
UpdateValueIfNeeded(false);
ExecutionContext exe_ctx (GetExecutionContextRef());
- Error error = m_value.GetValueAsData(&exe_ctx, data, 0, GetModule().get());
+ error = m_value.GetValueAsData(&exe_ctx, data, 0, GetModule().get());
if (error.Fail())
{
if (m_data.GetByteSize())
@@ -1707,7 +1705,7 @@ ValueObject::DumpPrintableRepresentation(Stream& s,
break;
case eValueObjectRepresentationStyleChildrenCount:
- strm.Printf("%zu", GetNumChildren());
+ strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildren());
cstr = strm.GetString().c_str();
break;
@@ -1955,6 +1953,12 @@ ValueObject::GetTypeName()
}
ConstString
+ValueObject::GetDisplayTypeName()
+{
+ return GetTypeName();
+}
+
+ConstString
ValueObject::GetQualifiedTypeName()
{
return GetClangType().GetConstQualifiedTypeName();
@@ -2063,7 +2067,7 @@ ValueObject::GetSyntheticArrayMemberFromPointer (size_t index, bool can_create)
if (IsPointerType ())
{
char index_str[64];
- snprintf(index_str, sizeof(index_str), "[%zu]", index);
+ snprintf(index_str, sizeof(index_str), "[%" PRIu64 "]", (uint64_t)index);
ConstString index_const_str(index_str);
// Check if we have already created a synthetic array member in this
// valid object. If we have we will re-use it.
@@ -2106,7 +2110,7 @@ ValueObject::GetSyntheticArrayMemberFromArray (size_t index, bool can_create)
if (IsArrayType ())
{
char index_str[64];
- snprintf(index_str, sizeof(index_str), "[%zu]", index);
+ snprintf(index_str, sizeof(index_str), "[%" PRIu64 "]", (uint64_t)index);
ConstString index_const_str(index_str);
// Check if we have already created a synthetic array member in this
// valid object. If we have we will re-use it.
@@ -2211,6 +2215,47 @@ ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type
return synthetic_child_sp;
}
+ValueObjectSP
+ValueObject::GetSyntheticBase (uint32_t offset, const ClangASTType& type, bool can_create)
+{
+ ValueObjectSP synthetic_child_sp;
+
+ char name_str[64];
+ snprintf(name_str, sizeof(name_str), "%s", type.GetTypeName().AsCString("<unknown>"));
+ ConstString name_const_str(name_str);
+
+ // Check if we have already created a synthetic array member in this
+ // valid object. If we have we will re-use it.
+ synthetic_child_sp = GetSyntheticChild (name_const_str);
+
+ if (synthetic_child_sp.get())
+ return synthetic_child_sp;
+
+ if (!can_create)
+ return ValueObjectSP();
+
+ const bool is_base_class = true;
+
+ ValueObjectChild *synthetic_child = new ValueObjectChild(*this,
+ type,
+ name_const_str,
+ type.GetByteSize(),
+ offset,
+ 0,
+ 0,
+ is_base_class,
+ false,
+ eAddressTypeInvalid);
+ if (synthetic_child)
+ {
+ AddSyntheticChild(name_const_str, synthetic_child);
+ synthetic_child_sp = synthetic_child->GetSP();
+ synthetic_child_sp->SetName(name_const_str);
+ }
+ return synthetic_child_sp;
+}
+
+
// your expression path needs to have a leading . or ->
// (unless it somehow "looks like" an array, in which case it has
// a leading [ symbol). while the [ is meaningful and should be shown
@@ -2392,6 +2437,26 @@ ValueObject::GetNonBaseClassParent()
return NULL;
}
+
+bool
+ValueObject::IsBaseClass (uint32_t& depth)
+{
+ if (!IsBaseClass())
+ {
+ depth = 0;
+ return false;
+ }
+ if (GetParent())
+ {
+ GetParent()->IsBaseClass(depth);
+ depth = depth + 1;
+ return true;
+ }
+ // TODO: a base of no parent? weird..
+ depth = 1;
+ return true;
+}
+
void
ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat)
{
@@ -3464,6 +3529,38 @@ ValueObject::CreateConstantValue (const ConstString &name)
return valobj_sp;
}
+lldb::addr_t
+ValueObject::GetCPPVTableAddress (AddressType &address_type)
+{
+ ClangASTType pointee_type;
+ ClangASTType this_type(GetClangType());
+ uint32_t type_info = this_type.GetTypeInfo(&pointee_type);
+ if (type_info)
+ {
+ bool ptr_or_ref = false;
+ if (type_info & (ClangASTType::eTypeIsPointer | ClangASTType::eTypeIsReference))
+ {
+ ptr_or_ref = true;
+ type_info = pointee_type.GetTypeInfo();
+ }
+
+ const uint32_t cpp_class = ClangASTType::eTypeIsClass | ClangASTType::eTypeIsCPlusPlus;
+ if ((type_info & cpp_class) == cpp_class)
+ {
+ if (ptr_or_ref)
+ {
+ address_type = GetAddressTypeOfChildren();
+ return GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ }
+ else
+ return GetAddressOf (false, &address_type);
+ }
+ }
+
+ address_type = eAddressTypeInvalid;
+ return LLDB_INVALID_ADDRESS;
+}
+
ValueObjectSP
ValueObject::Dereference (Error &error)
{
@@ -3490,7 +3587,6 @@ ValueObject::Dereference (Error &error)
ExecutionContext exe_ctx (GetExecutionContextRef());
child_clang_type = clang_type.GetChildClangTypeAtIndex (&exe_ctx,
- GetName().GetCString(),
0,
transparent_pointers,
omit_empty_base_classes,
@@ -3501,7 +3597,8 @@ ValueObject::Dereference (Error &error)
child_bitfield_bit_size,
child_bitfield_bit_offset,
child_is_base_class,
- child_is_deref_of_parent);
+ child_is_deref_of_parent,
+ this);
if (child_clang_type && child_byte_size)
{
ConstString child_name;
@@ -3881,7 +3978,7 @@ ValueObject::CreateValueObjectFromAddress (const char* name,
lldb::ValueObjectSP
ValueObject::CreateValueObjectFromData (const char* name,
- DataExtractor& data,
+ const DataExtractor& data,
const ExecutionContext& exe_ctx,
ClangASTType type)
{
diff --git a/source/Core/ValueObjectChild.cpp b/source/Core/ValueObjectChild.cpp
index ccf87cd15b24..33b91f9e30d1 100644
--- a/source/Core/ValueObjectChild.cpp
+++ b/source/Core/ValueObjectChild.cpp
@@ -66,25 +66,29 @@ ValueObjectChild::CalculateNumChildren()
return GetClangType().GetNumChildren (true);
}
+static void
+AdjustForBitfieldness(ConstString& name,
+ uint8_t bitfield_bit_size)
+{
+ if (name && bitfield_bit_size)
+ {
+ const char *clang_type_name = name.AsCString();
+ if (clang_type_name)
+ {
+ std::vector<char> bitfield_type_name (strlen(clang_type_name) + 32, 0);
+ ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", clang_type_name, bitfield_bit_size);
+ name.SetCString(&bitfield_type_name.front());
+ }
+ }
+}
+
ConstString
ValueObjectChild::GetTypeName()
{
if (m_type_name.IsEmpty())
{
m_type_name = GetClangType().GetConstTypeName ();
- if (m_type_name)
- {
- if (m_bitfield_bit_size > 0)
- {
- const char *clang_type_name = m_type_name.AsCString();
- if (clang_type_name)
- {
- std::vector<char> bitfield_type_name (strlen(clang_type_name) + 32, 0);
- ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", clang_type_name, m_bitfield_bit_size);
- m_type_name.SetCString(&bitfield_type_name.front());
- }
- }
- }
+ AdjustForBitfieldness(m_type_name, m_bitfield_bit_size);
}
return m_type_name;
}
@@ -93,22 +97,18 @@ ConstString
ValueObjectChild::GetQualifiedTypeName()
{
ConstString qualified_name = GetClangType().GetConstTypeName();
- if (qualified_name)
- {
- if (m_bitfield_bit_size > 0)
- {
- const char *clang_type_name = qualified_name.AsCString();
- if (clang_type_name)
- {
- std::vector<char> bitfield_type_name (strlen(clang_type_name) + 32, 0);
- ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", clang_type_name, m_bitfield_bit_size);
- qualified_name.SetCString(&bitfield_type_name.front());
- }
- }
- }
+ AdjustForBitfieldness(qualified_name, m_bitfield_bit_size);
return qualified_name;
}
+ConstString
+ValueObjectChild::GetDisplayTypeName()
+{
+ ConstString display_name = GetClangType().GetDisplayTypeName();
+ AdjustForBitfieldness(display_name, m_bitfield_bit_size);
+ return display_name;
+}
+
bool
ValueObjectChild::UpdateValue ()
{
diff --git a/source/Core/ValueObjectConstResult.cpp b/source/Core/ValueObjectConstResult.cpp
index d6d86381358d..387e171e3526 100644
--- a/source/Core/ValueObjectConstResult.cpp
+++ b/source/Core/ValueObjectConstResult.cpp
@@ -276,6 +276,12 @@ ValueObjectConstResult::GetTypeName()
return m_type_name;
}
+ConstString
+ValueObjectConstResult::GetDisplayTypeName()
+{
+ return GetClangType().GetDisplayTypeName();
+}
+
bool
ValueObjectConstResult::UpdateValue ()
{
diff --git a/source/Core/ValueObjectConstResultImpl.cpp b/source/Core/ValueObjectConstResultImpl.cpp
index e0757f60cdba..d3e275883509 100644
--- a/source/Core/ValueObjectConstResultImpl.cpp
+++ b/source/Core/ValueObjectConstResultImpl.cpp
@@ -31,7 +31,7 @@ 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 knowning how to set the address type of its children correctly. the alternative implementation
+// 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
@@ -109,7 +109,6 @@ ValueObjectConstResultImpl::CreateChildAtIndex (size_t idx, bool synthetic_array
ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
child_clang_type = clang_type.GetChildClangTypeAtIndex (&exe_ctx,
- m_impl_backend->GetName().GetCString(),
idx,
transparent_pointers,
omit_empty_base_classes,
@@ -120,7 +119,8 @@ ValueObjectConstResultImpl::CreateChildAtIndex (size_t idx, bool synthetic_array
child_bitfield_bit_size,
child_bitfield_bit_offset,
child_is_base_class,
- child_is_deref_of_parent);
+ child_is_deref_of_parent,
+ m_impl_backend);
if (child_clang_type && child_byte_size)
{
if (synthetic_index)
diff --git a/source/Core/ValueObjectDynamicValue.cpp b/source/Core/ValueObjectDynamicValue.cpp
index 47e781e71156..a6fad7a9b1fd 100644
--- a/source/Core/ValueObjectDynamicValue.cpp
+++ b/source/Core/ValueObjectDynamicValue.cpp
@@ -71,8 +71,6 @@ ValueObjectDynamicValue::GetTypeName()
{
if (m_dynamic_type_info.HasName())
return m_dynamic_type_info.GetName();
- if (m_dynamic_type_info.HasType())
- return GetClangType().GetConstTypeName();
}
return m_parent->GetTypeName();
}
@@ -96,10 +94,22 @@ ValueObjectDynamicValue::GetQualifiedTypeName()
{
if (m_dynamic_type_info.HasName())
return m_dynamic_type_info.GetName();
+ }
+ return m_parent->GetQualifiedTypeName();
+}
+
+ConstString
+ValueObjectDynamicValue::GetDisplayTypeName()
+{
+ const bool success = UpdateValueIfNeeded(false);
+ if (success)
+ {
if (m_dynamic_type_info.HasType())
- return GetClangType().GetConstQualifiedTypeName ();
+ return GetClangType().GetDisplayTypeName();
+ if (m_dynamic_type_info.HasName())
+ return m_dynamic_type_info.GetName();
}
- return m_parent->GetTypeName();
+ return m_parent->GetDisplayTypeName();
}
size_t
@@ -175,7 +185,7 @@ ValueObjectDynamicValue::UpdateValue ()
m_error = m_parent->GetError();
return false;
}
-
+
// Setting our type_sp to NULL will route everything back through our
// parent which is equivalent to not using dynamic values.
if (m_use_dynamic == lldb::eNoDynamicValues)
@@ -183,7 +193,7 @@ ValueObjectDynamicValue::UpdateValue ()
m_dynamic_type_info.Clear();
return true;
}
-
+
ExecutionContext exe_ctx (GetExecutionContextRef());
Target *target = exe_ctx.GetTargetPtr();
if (target)
@@ -191,16 +201,16 @@ ValueObjectDynamicValue::UpdateValue ()
m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
}
-
+
// First make sure our Type and/or Address haven't changed:
Process *process = exe_ctx.GetProcessPtr();
if (!process)
return false;
-
+
TypeAndOrName class_type_or_name;
Address dynamic_address;
bool found_dynamic_type = false;
-
+
lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC)
{
@@ -213,7 +223,7 @@ ValueObjectDynamicValue::UpdateValue ()
LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus);
if (cpp_runtime)
found_dynamic_type = cpp_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
-
+
if (!found_dynamic_type)
{
LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
@@ -221,10 +231,10 @@ ValueObjectDynamicValue::UpdateValue ()
found_dynamic_type = objc_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
}
}
-
+
// Getting the dynamic value may have run the program a bit, and so marked us as needing updating, but we really
// don't...
-
+
m_update_point.SetUpdated();
if (found_dynamic_type)
@@ -251,7 +261,7 @@ ValueObjectDynamicValue::UpdateValue ()
{
m_type_impl.Clear();
}
-
+
// If we don't have a dynamic type, then make ourselves just a echo of our parent.
// Or we could return false, and make ourselves an echo of our parent?
if (!found_dynamic_type)
@@ -264,13 +274,13 @@ ValueObjectDynamicValue::UpdateValue ()
m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
return m_error.Success();
}
-
+
Value old_value(m_value);
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
-
+
bool has_changed_type = false;
-
+
if (!m_dynamic_type_info)
{
m_dynamic_type_info = class_type_or_name;
@@ -283,37 +293,35 @@ ValueObjectDynamicValue::UpdateValue ()
SetValueDidChange (true);
has_changed_type = true;
}
-
+
if (has_changed_type)
ClearDynamicTypeInformation ();
-
+
if (!m_address.IsValid() || m_address != dynamic_address)
{
if (m_address.IsValid())
SetValueDidChange (true);
-
+
// We've moved, so we should be fine...
m_address = dynamic_address;
lldb::TargetSP target_sp (GetTargetSP());
lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
m_value.GetScalar() = load_address;
}
-
+
m_dynamic_type_info = FixupTypeAndOrName(m_dynamic_type_info, *m_parent);
-
+
//m_value.SetContext (Value::eContextTypeClangType, corrected_type);
m_value.SetClangType (m_dynamic_type_info.GetClangASTType());
-
+
// Our address is the location of the dynamic type stored in memory. It isn't a load address,
// because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us...
m_value.SetValueType(Value::eValueTypeScalar);
if (has_changed_type && log)
- log->Printf("[%s %p] has a new dynamic type %s",
- GetName().GetCString(),
- this,
- GetTypeName().GetCString());
-
+ log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(),
+ static_cast<void*>(this), GetTypeName().GetCString());
+
if (m_address.IsValid() && m_dynamic_type_info)
{
// The variable value is in the Scalar value inside the m_value.
@@ -333,7 +341,7 @@ ValueObjectDynamicValue::UpdateValue ()
return true;
}
}
-
+
// We get here if we've failed above...
SetValueIsValid (false);
return false;
diff --git a/source/Core/ValueObjectMemory.cpp b/source/Core/ValueObjectMemory.cpp
index 42fd0e8fffba..d2cbbfdda240 100644
--- a/source/Core/ValueObjectMemory.cpp
+++ b/source/Core/ValueObjectMemory.cpp
@@ -147,6 +147,14 @@ ValueObjectMemory::GetTypeName()
return m_clang_type.GetConstTypeName();
}
+ConstString
+ValueObjectMemory::GetDisplayTypeName()
+{
+ if (m_type_sp)
+ return m_type_sp->GetClangForwardType().GetDisplayTypeName();
+ return m_clang_type.GetDisplayTypeName();
+}
+
size_t
ValueObjectMemory::CalculateNumChildren()
{
diff --git a/source/Core/ValueObjectRegister.cpp b/source/Core/ValueObjectRegister.cpp
index 4f21457519ec..0db1f0cd45cf 100644
--- a/source/Core/ValueObjectRegister.cpp
+++ b/source/Core/ValueObjectRegister.cpp
@@ -55,6 +55,12 @@ ValueObjectRegisterContext::GetTypeName()
}
ConstString
+ValueObjectRegisterContext::GetDisplayTypeName()
+{
+ return ConstString();
+}
+
+ConstString
ValueObjectRegisterContext::GetQualifiedTypeName()
{
return ConstString();
diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp
index a65b8f63e317..18d36164989a 100644
--- a/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/source/Core/ValueObjectSyntheticFilter.cpp
@@ -101,6 +101,12 @@ ValueObjectSynthetic::GetQualifiedTypeName()
return m_parent->GetQualifiedTypeName();
}
+ConstString
+ValueObjectSynthetic::GetDisplayTypeName()
+{
+ return m_parent->GetDisplayTypeName();
+}
+
size_t
ValueObjectSynthetic::CalculateNumChildren()
{
diff --git a/source/Core/ValueObjectVariable.cpp b/source/Core/ValueObjectVariable.cpp
index 2e5bb22a890c..225dc02c8add 100644
--- a/source/Core/ValueObjectVariable.cpp
+++ b/source/Core/ValueObjectVariable.cpp
@@ -73,6 +73,15 @@ ValueObjectVariable::GetTypeName()
}
ConstString
+ValueObjectVariable::GetDisplayTypeName()
+{
+ Type * var_type = m_variable_sp->GetType();
+ if (var_type)
+ return var_type->GetClangForwardType().GetDisplayTypeName();
+ return ConstString();
+}
+
+ConstString
ValueObjectVariable::GetQualifiedTypeName()
{
Type * var_type = m_variable_sp->GetType();
diff --git a/source/DataFormatters/CF.cpp b/source/DataFormatters/CF.cpp
index a4b7a1235ffa..e131b68096fd 100644
--- a/source/DataFormatters/CF.cpp
+++ b/source/DataFormatters/CF.cpp
@@ -85,7 +85,7 @@ lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& str
ValueObjectSP count_sp;
StreamString expr;
expr.Printf("(int)CFBagGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue());
- if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExecutionCompleted)
+ if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExpressionCompleted)
return false;
if (!count_sp)
return false;
@@ -160,7 +160,7 @@ lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Strea
if (error.Fail() || num_bytes == 0)
return false;
uint8_t *bytes = buffer_sp->GetBytes();
- for (int byte_idx = 0; byte_idx < num_bytes-1; byte_idx++)
+ for (uint64_t byte_idx = 0; byte_idx < num_bytes-1; byte_idx++)
{
uint8_t byte = bytes[byte_idx];
bool bit0 = (byte & 1) == 1;
@@ -279,7 +279,7 @@ lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stre
ValueObjectSP count_sp;
StreamString expr;
expr.Printf("(int)CFBinaryHeapGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue());
- if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExecutionCompleted)
+ if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExpressionCompleted)
return false;
if (!count_sp)
return false;
diff --git a/source/DataFormatters/CXXFormatterFunctions.cpp b/source/DataFormatters/CXXFormatterFunctions.cpp
index 136c8c51e660..ae5b35fd2b1c 100644
--- a/source/DataFormatters/CXXFormatterFunctions.cpp
+++ b/source/DataFormatters/CXXFormatterFunctions.cpp
@@ -20,8 +20,8 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
#include <algorithm>
@@ -29,6 +29,23 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
+StackFrame*
+lldb_private::formatters::GetViableFrame (ExecutionContext exe_ctx)
+{
+ StackFrame* frame = exe_ctx.GetFramePtr();
+ if (frame)
+ return frame;
+
+ Process* process = exe_ctx.GetProcessPtr();
+ if (!process)
+ return nullptr;
+
+ ThreadSP thread_sp(process->GetThreadList().GetSelectedThread());
+ if (thread_sp)
+ return thread_sp->GetSelectedFrame().get();
+ return nullptr;
+}
+
bool
lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
const char* target_type,
@@ -44,7 +61,7 @@ lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
lldb::ValueObjectSP result_sp;
Target* target = exe_ctx.GetTargetPtr();
- StackFrame* stack_frame = exe_ctx.GetFramePtr();
+ StackFrame* stack_frame = GetViableFrame(exe_ctx);
if (!target || !stack_frame)
return false;
@@ -78,7 +95,7 @@ lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
lldb::ValueObjectSP result_sp;
Target* target = exe_ctx.GetTargetPtr();
- StackFrame* stack_frame = exe_ctx.GetFramePtr();
+ StackFrame* stack_frame = GetViableFrame(exe_ctx);
if (!target || !stack_frame)
return false;
@@ -116,7 +133,7 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
lldb::ValueObjectSP result_sp;
Target* target = exe_ctx.GetTargetPtr();
- StackFrame* stack_frame = exe_ctx.GetFramePtr();
+ StackFrame* stack_frame = GetViableFrame(exe_ctx);
if (!target || !stack_frame)
return valobj_sp;
@@ -153,7 +170,7 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
lldb::ValueObjectSP result_sp;
Target* target = exe_ctx.GetTargetPtr();
- StackFrame* stack_frame = exe_ctx.GetFramePtr();
+ StackFrame* stack_frame = GetViableFrame(exe_ctx);
if (!target || !stack_frame)
return valobj_sp;
@@ -576,7 +593,11 @@ bool
lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
{
DataExtractor data;
- valobj.GetData(data);
+ Error error;
+ valobj.GetData(data, error);
+
+ if (error.Fail())
+ return false;
std::string value;
valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
@@ -590,7 +611,11 @@ bool
lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
{
DataExtractor data;
- valobj.GetData(data);
+ Error error;
+ valobj.GetData(data, error);
+
+ if (error.Fail())
+ return false;
std::string value;
valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
@@ -604,7 +629,11 @@ bool
lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
{
DataExtractor data;
- valobj.GetData(data);
+ Error error;
+ valobj.GetData(data, error);
+
+ if (error.Fail())
+ return false;
clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
@@ -954,6 +983,61 @@ ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
}
bool
+lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream)
+{
+ if (!descriptor)
+ return false;
+ uint64_t len_bits = 0, data_bits = 0;
+ if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
+ return false;
+
+ static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
+ static const int g_SixbitMaxLen = 9;
+ static const int g_fiveBitMaxLen = 11;
+
+ static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
+
+ if (len_bits > g_fiveBitMaxLen)
+ return false;
+
+ // this is a fairly ugly trick - pretend that the numeric value is actually a char*
+ // this works under a few assumptions:
+ // little endian architecture
+ // sizeof(uint64_t) > g_MaxNonBitmaskedLen
+ if (len_bits <= g_MaxNonBitmaskedLen)
+ {
+ stream.Printf("@\"%s\"",(const char*)&data_bits);
+ return true;
+ }
+
+ // if the data is bitmasked, we need to actually process the bytes
+ uint8_t bitmask = 0;
+ uint8_t shift_offset = 0;
+
+ if (len_bits <= g_SixbitMaxLen)
+ {
+ bitmask = 0x03f;
+ shift_offset = 6;
+ }
+ else
+ {
+ bitmask = 0x01f;
+ shift_offset = 5;
+ }
+
+ std::vector<uint8_t> bytes;
+ bytes.resize(len_bits);
+ for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
+ {
+ uint8_t packed = data_bits & bitmask;
+ bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
+ }
+
+ stream.Printf("@\"%s\"",&bytes[0]);
+ return true;
+}
+
+bool
lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
{
ProcessSP process_sp = valobj.GetProcessSP();
@@ -982,6 +1066,12 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream&
if (!class_name || !*class_name)
return false;
+ bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
+ // for a tagged pointer, the descriptor has everything we need
+ if (is_tagged_ptr)
+ return NSTaggedString_SummaryProvider(descriptor, stream);
+
+ // if not a tagged pointer that we know about, try the normal route
uint64_t info_bits_location = valobj_addr + ptr_size;
if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
info_bits_location += 3;
@@ -1144,7 +1234,10 @@ lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj
if (!child_ptr_sp)
return false;
DataExtractor data;
- child_ptr_sp->GetData(data);
+ Error error;
+ child_ptr_sp->GetData(data, error);
+ if (error.Fail())
+ return false;
ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
child_sp->GetValueAsUnsigned(0);
if (child_sp)
@@ -1218,7 +1311,10 @@ lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& s
else
{
DataExtractor data;
- valobj.GetData(data);
+ Error error;
+ valobj.GetData(data, error);
+ if (error.Fail())
+ return false;
valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
}
diff --git a/source/DataFormatters/Cocoa.cpp b/source/DataFormatters/Cocoa.cpp
index 555954db0bb7..8e92de4ddaa4 100644
--- a/source/DataFormatters/Cocoa.cpp
+++ b/source/DataFormatters/Cocoa.cpp
@@ -342,8 +342,7 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream&
stream.Printf("(long)%" PRId64,value);
break;
default:
- stream.Printf("unexpected value:(info=%" PRIu64 ", value=%" PRIu64,i_bits,value);
- break;
+ return false;
}
return true;
}
@@ -402,8 +401,7 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream&
break;
}
default:
- stream.Printf("unexpected value: dt=%d",data_type);
- break;
+ return false;
}
return true;
}
diff --git a/source/DataFormatters/FormatManager.cpp b/source/DataFormatters/FormatManager.cpp
index 751e61284610..28d108f2410a 100644
--- a/source/DataFormatters/FormatManager.cpp
+++ b/source/DataFormatters/FormatManager.cpp
@@ -21,6 +21,7 @@
#include "lldb/Interpreter/ScriptInterpreterPython.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
+#include "llvm/ADT/STLExtras.h"
using namespace lldb;
using namespace lldb_private;
@@ -76,8 +77,7 @@ g_format_infos[] =
{ eFormatVoid , 'v' , "void" }
};
-static uint32_t
-g_num_format_infos = sizeof(g_format_infos)/sizeof(FormatInfo);
+static uint32_t g_num_format_infos = llvm::array_lengthof(g_format_infos);
static bool
GetFormatFromFormatChar (char format_char, Format &format)
@@ -186,7 +186,11 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
}
entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
- if (clang_type.IsReferenceType())
+ ConstString display_type_name(clang_type.GetDisplayTypeName());
+ if (display_type_name != type_name)
+ entries.push_back({display_type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
+
+ for (bool is_rvalue_ref = true, j = true; j && clang_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false)
{
ClangASTType non_ref_type = clang_type.GetNonReferenceType();
GetPossibleMatches(valobj,
@@ -197,8 +201,22 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
did_strip_ptr,
true,
did_strip_typedef);
+ if (non_ref_type.IsTypedefType())
+ {
+ ClangASTType deffed_referenced_type = non_ref_type.GetTypedefedType();
+ deffed_referenced_type = is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() : deffed_referenced_type.GetLValueReferenceType();
+ GetPossibleMatches(valobj,
+ deffed_referenced_type,
+ reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
+ use_dynamic,
+ entries,
+ did_strip_ptr,
+ did_strip_ref,
+ true); // this is not exactly the usual meaning of stripping typedefs
+ }
}
- else if (clang_type.IsPointerType())
+
+ if (clang_type.IsPointerType())
{
ClangASTType non_ptr_type = clang_type.GetPointeeType();
GetPossibleMatches(valobj,
@@ -209,6 +227,18 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
true,
did_strip_ref,
did_strip_typedef);
+ if (non_ptr_type.IsTypedefType())
+ {
+ ClangASTType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType();
+ GetPossibleMatches(valobj,
+ deffed_pointed_type,
+ reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
+ use_dynamic,
+ entries,
+ did_strip_ptr,
+ did_strip_ref,
+ true); // this is not exactly the usual meaning of stripping typedefs
+ }
}
bool canBeObjCDynamic = clang_type.IsPossibleDynamicType (NULL,
false, // no C
@@ -507,7 +537,7 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj)
if (child_sp->GetSummaryFormat())
{
// and it wants children, then bail out
- if (child_sp->GetSummaryFormat()->DoesPrintChildren())
+ if (child_sp->GetSummaryFormat()->DoesPrintChildren(child_sp.get()))
return false;
}
@@ -553,11 +583,17 @@ GetTypeForCache (ValueObject& valobj,
return ConstString();
}
-static lldb::TypeFormatImplSP
-GetHardcodedFormat (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+lldb::TypeFormatImplSP
+FormatManager::GetHardcodedFormat (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
{
- return lldb::TypeFormatImplSP();
+ for (const auto& candidate: m_hardcoded_formats)
+ {
+ auto result = candidate(valobj,use_dynamic,*this);
+ if (result)
+ return result;
+ }
+ return nullptr;
}
lldb::TypeFormatImplSP
@@ -591,10 +627,12 @@ FormatManager::GetFormat (ValueObject& valobj,
log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded a chance.");
retval = GetHardcodedFormat(valobj, use_dynamic);
}
- if (valobj_type)
+ else if (valobj_type)
{
if (log)
- log->Printf("[FormatManager::GetFormat] Caching %p for type %s",retval.get(),valobj_type.AsCString("<invalid>"));
+ log->Printf("[FormatManager::GetFormat] Caching %p for type %s",
+ static_cast<void*>(retval.get()),
+ valobj_type.AsCString("<invalid>"));
m_format_cache.SetFormat(valobj_type,retval);
}
if (log && log->GetDebug())
@@ -602,11 +640,17 @@ FormatManager::GetFormat (ValueObject& valobj,
return retval;
}
-static lldb::TypeSummaryImplSP
-GetHardcodedSummaryFormat (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+lldb::TypeSummaryImplSP
+FormatManager::GetHardcodedSummaryFormat (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
{
- return lldb::TypeSummaryImplSP();
+ for (const auto& candidate: m_hardcoded_summaries)
+ {
+ auto result = candidate(valobj,use_dynamic,*this);
+ if (result)
+ return result;
+ }
+ return nullptr;
}
lldb::TypeSummaryImplSP
@@ -640,10 +684,12 @@ FormatManager::GetSummaryFormat (ValueObject& valobj,
log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving hardcoded a chance.");
retval = GetHardcodedSummaryFormat(valobj, use_dynamic);
}
- if (valobj_type)
+ else if (valobj_type)
{
if (log)
- log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s",retval.get(),valobj_type.AsCString("<invalid>"));
+ log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s",
+ static_cast<void*>(retval.get()),
+ valobj_type.AsCString("<invalid>"));
m_format_cache.SetSummary(valobj_type,retval);
}
if (log && log->GetDebug())
@@ -652,11 +698,17 @@ FormatManager::GetSummaryFormat (ValueObject& valobj,
}
#ifndef LLDB_DISABLE_PYTHON
-static lldb::SyntheticChildrenSP
-GetHardcodedSyntheticChildren (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+lldb::SyntheticChildrenSP
+FormatManager::GetHardcodedSyntheticChildren (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
{
- return lldb::SyntheticChildrenSP();
+ for (const auto& candidate: m_hardcoded_synthetics)
+ {
+ auto result = candidate(valobj,use_dynamic,*this);
+ if (result)
+ return result;
+ }
+ return nullptr;
}
lldb::SyntheticChildrenSP
@@ -690,10 +742,12 @@ FormatManager::GetSyntheticChildren (ValueObject& valobj,
log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving hardcoded a chance.");
retval = GetHardcodedSyntheticChildren(valobj, use_dynamic);
}
- if (valobj_type)
+ else if (valobj_type)
{
if (log)
- log->Printf("[FormatManager::GetSyntheticChildren] Caching %p for type %s",retval.get(),valobj_type.AsCString("<invalid>"));
+ log->Printf("[FormatManager::GetSyntheticChildren] Caching %p for type %s",
+ static_cast<void*>(retval.get()),
+ valobj_type.AsCString("<invalid>"));
m_format_cache.SetSynthetic(valobj_type,retval);
}
if (log && log->GetDebug())
@@ -716,12 +770,17 @@ FormatManager::FormatManager() :
m_coregraphics_category_name(ConstString("CoreGraphics")),
m_coreservices_category_name(ConstString("CoreServices")),
m_vectortypes_category_name(ConstString("VectorTypes")),
- m_appkit_category_name(ConstString("AppKit"))
+ m_appkit_category_name(ConstString("AppKit")),
+ m_hardcoded_formats(),
+ m_hardcoded_summaries(),
+ m_hardcoded_synthetics()
+
{
LoadSystemFormatters();
LoadLibStdcppFormatters();
LoadLibcxxFormatters();
LoadObjCFormatters();
+ LoadHardcodedFormatters();
EnableCategory(m_objc_category_name,TypeCategoryMap::Last);
EnableCategory(m_corefoundation_category_name,TypeCategoryMap::Last);
@@ -768,28 +827,6 @@ AddStringSummary(TypeCategoryImpl::SharedPointer category_sp,
#ifndef LLDB_DISABLE_PYTHON
static void
-AddScriptSummary(TypeCategoryImpl::SharedPointer category_sp,
- const char* funct_name,
- ConstString type_name,
- TypeSummaryImpl::Flags flags,
- bool regex = false)
-{
-
- std::string code(" ");
- code.append(funct_name).append("(valobj,internal_dict)");
-
- lldb::TypeSummaryImplSP summary_sp(new ScriptSummaryFormat(flags,
- funct_name,
- code.c_str()));
- if (regex)
- category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
- else
- category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
-}
-#endif
-
-#ifndef LLDB_DISABLE_PYTHON
-static void
AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp,
CXXFunctionSummaryFormat::Callback funct,
const char* description,
@@ -956,6 +993,7 @@ FormatManager::LoadLibcxxFormatters()
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_synth_flags, true);
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::map synthetic children", ConstString("^std::__1::map<.+> >(( )?&)?$"), stl_synth_flags, true);
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_synth_flags);
+ AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags);
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::set synthetic children", ConstString("^std::__1::set<.+> >(( )?&)?$"), stl_synth_flags, true);
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);
@@ -969,12 +1007,14 @@ FormatManager::LoadLibcxxFormatters()
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "weak_ptr synthetic children", ConstString("^(std::__1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(false);
+ AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags);
AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_summary_flags, true);
AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_summary_flags, true);
AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", ConstString("^std::__1::map<.+>(( )?&)?$"), stl_summary_flags, true);
AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::deque summary provider", ConstString("^std::__1::deque<.+>(( )?&)?$"), stl_summary_flags, true);
AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_summary_flags);
+ AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags);
AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__1::set<.+>(( )?&)?$"), stl_summary_flags, true);
AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multiset summary provider", ConstString("^std::__1::multiset<.+>(( )?&)?$"), stl_summary_flags, true);
AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multimap summary provider", ConstString("^std::__1::multimap<.+>(( )?&)?$"), stl_summary_flags, true);
@@ -987,6 +1027,7 @@ FormatManager::LoadLibcxxFormatters()
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^std::__1::__wrap_iter<.+>$"), stl_synth_flags, true);
+ AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags);
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::__1::__map_iterator<.+>$"), stl_synth_flags, true);
AddFilter(libcxx_category_sp, {"__a_"}, "libc++ std::atomic filter", ConstString("^std::__1::atomic<.*>$"), stl_synth_flags, true);
@@ -1253,6 +1294,7 @@ FormatManager::LoadObjCFormatters()
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryM"), ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryI"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSCFDictionary"), ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSDictionary"), ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSMutableDictionary"), ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFDictionaryRef"), ScriptedSyntheticChildren::Flags());
@@ -1294,6 +1336,7 @@ FormatManager::LoadObjCFormatters()
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSData"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteData"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteMutableData"), appkit_flags);
+ AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSMutableData"), appkit_flags);
AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("__NSCFData"), appkit_flags);
AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFDataRef"), appkit_flags);
AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags);
@@ -1419,3 +1462,17 @@ FormatManager::LoadObjCFormatters()
ConstString("vBool32"),
vector_flags);
}
+
+void
+FormatManager::LoadHardcodedFormatters()
+{
+ {
+ // insert code to load formats here
+ }
+ {
+ // insert code to load summaries here
+ }
+ {
+ // insert code to load synthetics here
+ }
+}
diff --git a/source/DataFormatters/LibCxx.cpp b/source/DataFormatters/LibCxx.cpp
index 6380d971a177..174202661f03 100644
--- a/source/DataFormatters/LibCxx.cpp
+++ b/source/DataFormatters/LibCxx.cpp
@@ -139,13 +139,11 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (si
return ValueObjectSP();
}
bool bit_set = ((byte & mask) != 0);
- ValueObjectSP retval_sp;
DataBufferSP buffer_sp(new DataBufferHeap(m_bool_type.GetByteSize(),0));
if (bit_set && buffer_sp && buffer_sp->GetBytes())
*(buffer_sp->GetBytes()) = 1; // regardless of endianness, anything non-zero is true
- StreamString name; name.Printf("[%zu]",idx);
- DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
- retval_sp = ValueObject::CreateValueObjectFromData(name.GetData(), data, m_exe_ctx_ref, m_bool_type);
+ 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));
if (retval_sp)
m_children[idx] = retval_sp;
return retval_sp;
@@ -168,8 +166,6 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
ValueObjectSP valobj_sp = m_backend.GetSP();
if (!valobj_sp)
return false;
- if (!valobj_sp)
- return false;
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
if (!size_sp)
@@ -499,7 +495,7 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (siz
uint64_t offset = idx * m_element_size;
offset = offset + m_start->GetValueAsUnsigned(0);
StreamString name;
- name.Printf("[%zu]",idx);
+ 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;
diff --git a/source/DataFormatters/LibCxxList.cpp b/source/DataFormatters/LibCxxList.cpp
index de2ca1b20459..7d6db1a0ccd4 100644
--- a/source/DataFormatters/LibCxxList.cpp
+++ b/source/DataFormatters/LibCxxList.cpp
@@ -33,20 +33,20 @@ public:
ListEntry (const ListEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {}
ListEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
- ValueObjectSP
+ ListEntry
next ()
{
if (!m_entry_sp)
- return m_entry_sp;
- return m_entry_sp->GetChildMemberWithName(ConstString("__next_"), true);
+ return ListEntry();
+ return ListEntry(m_entry_sp->GetChildMemberWithName(ConstString("__next_"), true));
}
- ValueObjectSP
+ ListEntry
prev ()
{
if (!m_entry_sp)
- return m_entry_sp;
- return m_entry_sp->GetChildMemberWithName(ConstString("__prev_"), true);
+ return ListEntry();
+ return ListEntry(m_entry_sp->GetChildMemberWithName(ConstString("__prev_"), true));
}
uint64_t
@@ -63,6 +63,11 @@ public:
return (value() == 0);
}
+ explicit operator bool ()
+ {
+ return GetEntry().get() != nullptr && null() == false;
+ }
+
ValueObjectSP
GetEntry ()
{
@@ -130,13 +135,13 @@ protected:
void
next ()
{
- m_entry.SetEntry(m_entry.next());
+ m_entry = m_entry.next();
}
void
prev ()
{
- m_entry.SetEntry(m_entry.prev());
+ m_entry = m_entry.prev();
}
private:
ListEntry m_entry;
@@ -161,17 +166,24 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop()
{
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;
ListEntry slow(m_head);
- ListEntry fast1(m_head);
- ListEntry fast2(m_head);
- while (slow.next() && slow.next()->GetValueAsUnsigned(0) != m_node_address)
+ ListEntry fast(m_head);
+ while (steps_left-- > 0)
{
- auto slow_value = slow.value();
- fast1.SetEntry(fast2.next());
- fast2.SetEntry(fast1.next());
- if (fast1.value() == slow_value || fast2.value() == slow_value)
+ slow = slow.next();
+ fast = fast.next();
+ if (fast.next())
+ fast = fast.next().next();
+ else
+ fast = nullptr;
+ if (!slow || !fast)
+ return false;
+ if (slow == fast)
return true;
- slow.SetEntry(slow.next());
}
return false;
}
@@ -212,10 +224,10 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::CalculateNumChildren (
return 0;
uint64_t size = 2;
ListEntry current(m_head);
- while (current.next() && current.next()->GetValueAsUnsigned(0) != m_node_address)
+ while (current.next() && current.next().value() != m_node_address)
{
size++;
- current.SetEntry(current.next());
+ current = current.next();
if (size > m_list_capping_size)
break;
}
@@ -245,9 +257,13 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_
return lldb::ValueObjectSP();
// we need to copy current_sp into a new object otherwise we will end up with all items named __value_
DataExtractor data;
- current_sp->GetData(data);
+ Error error;
+ current_sp->GetData(data, error);
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+
StreamString name;
- name.Printf("[%zu]",idx);
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
return (m_children[idx] = ValueObject::CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type));
}
diff --git a/source/DataFormatters/LibCxxMap.cpp b/source/DataFormatters/LibCxxMap.cpp
index 5daa40f15f3d..e665f29622d8 100644
--- a/source/DataFormatters/LibCxxMap.cpp
+++ b/source/DataFormatters/LibCxxMap.cpp
@@ -366,9 +366,15 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t
// at this point we have a valid
// we need to copy current_sp into a new object otherwise we will end up with all items named __value_
DataExtractor data;
- iterated_sp->GetData(data);
+ Error error;
+ iterated_sp->GetData(data, error);
+ if (error.Fail())
+ {
+ m_tree = NULL;
+ return lldb::ValueObjectSP();
+ }
StreamString name;
- name.Printf("[%zu]",idx);
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
return (m_children[idx] = ValueObject::CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type));
}
diff --git a/source/DataFormatters/LibCxxUnorderedMap.cpp b/source/DataFormatters/LibCxxUnorderedMap.cpp
index 05b41d0de0c8..bf68f20955b5 100644
--- a/source/DataFormatters/LibCxxUnorderedMap.cpp
+++ b/source/DataFormatters/LibCxxUnorderedMap.cpp
@@ -81,9 +81,12 @@ lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtInde
if (!val_hash.first)
return lldb::ValueObjectSP();
StreamString stream;
- stream.Printf("[%zu]",idx);
+ stream.Printf("[%" PRIu64 "]", (uint64_t)idx);
DataExtractor data;
- val_hash.first->GetData(data);
+ Error error;
+ val_hash.first->GetData(data, error);
+ if (error.Fail())
+ return lldb::ValueObjectSP();
const bool thread_and_frame_only_if_stopped = true;
ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped);
return val_hash.first->CreateValueObjectFromData(stream.GetData(),
diff --git a/source/DataFormatters/LibStdcpp.cpp b/source/DataFormatters/LibStdcpp.cpp
index 08e7d584003e..f2d617323cca 100644
--- a/source/DataFormatters/LibStdcpp.cpp
+++ b/source/DataFormatters/LibStdcpp.cpp
@@ -93,7 +93,7 @@ lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetChildAtIndex
target.EvaluateExpression("(bool)true", NULL, retval_sp);
else
target.EvaluateExpression("(bool)false", NULL, retval_sp);
- StreamString name; name.Printf("[%zu]",idx);
+ StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx);
if (retval_sp)
retval_sp->SetName(ConstString(name.GetData()));
return retval_sp;
diff --git a/source/DataFormatters/NSArray.cpp b/source/DataFormatters/NSArray.cpp
index d8ee9bfa8a47..16635381f94f 100644
--- a/source/DataFormatters/NSArray.cpp
+++ b/source/DataFormatters/NSArray.cpp
@@ -19,12 +19,214 @@
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
#include "lldb/Target/Target.h"
+#include "clang/AST/ASTContext.h"
+
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
+namespace lldb_private {
+ namespace formatters {
+ class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update() = 0;
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~NSArrayMSyntheticFrontEnd () {}
+
+ protected:
+ virtual lldb::addr_t
+ GetDataAddress () = 0;
+
+ virtual uint64_t
+ GetUsedCount () = 0;
+
+ virtual uint64_t
+ GetOffset () = 0;
+
+ virtual uint64_t
+ GetSize () = 0;
+
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ ClangASTType m_id_type;
+ std::vector<lldb::ValueObjectSP> m_children;
+ };
+
+ class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd
+ {
+ private:
+ struct DataDescriptor_32
+ {
+ uint32_t _used;
+ uint32_t _priv1 : 2 ;
+ uint32_t _size : 30;
+ uint32_t _priv2 : 2;
+ uint32_t _offset : 30;
+ uint32_t _priv3;
+ uint32_t _data;
+ };
+ struct DataDescriptor_64
+ {
+ uint64_t _used;
+ uint64_t _priv1 : 2 ;
+ uint64_t _size : 62;
+ uint64_t _priv2 : 2;
+ uint64_t _offset : 62;
+ uint32_t _priv3;
+ uint64_t _data;
+ };
+ public:
+ NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp);
+
+ virtual bool
+ Update();
+
+ virtual
+ ~NSArrayMSyntheticFrontEnd_109 ();
+
+ protected:
+ virtual lldb::addr_t
+ GetDataAddress ();
+
+ virtual uint64_t
+ GetUsedCount ();
+
+ virtual uint64_t
+ GetOffset ();
+
+ virtual uint64_t
+ GetSize ();
+
+ private:
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ };
+
+ class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd
+ {
+ private:
+ struct DataDescriptor_32
+ {
+ uint32_t _used;
+ uint32_t _offset;
+ uint32_t _size : 28;
+ uint64_t _priv1 : 4;
+ uint32_t _priv2;
+ uint32_t _data;
+ };
+ struct DataDescriptor_64
+ {
+ uint64_t _used;
+ uint64_t _offset;
+ uint64_t _size : 60;
+ uint64_t _priv1 : 4;
+ uint32_t _priv2;
+ uint64_t _data;
+ };
+ public:
+ NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp);
+
+ virtual bool
+ Update();
+
+ virtual
+ ~NSArrayMSyntheticFrontEnd_1010 ();
+
+ protected:
+ virtual lldb::addr_t
+ GetDataAddress ();
+
+ virtual uint64_t
+ GetUsedCount ();
+
+ virtual uint64_t
+ GetOffset ();
+
+ virtual uint64_t
+ GetSize ();
+
+ private:
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ };
+
+ class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSArrayISyntheticFrontEnd (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
+ ~NSArrayISyntheticFrontEnd ();
+ private:
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ uint64_t m_items;
+ lldb::addr_t m_data_ptr;
+ ClangASTType m_id_type;
+ std::vector<lldb::ValueObjectSP> m_children;
+ };
+
+ class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSArrayCodeRunningSyntheticFrontEnd (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
+ ~NSArrayCodeRunningSyntheticFrontEnd ();
+ };
+ }
+}
+
bool
lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream)
{
@@ -90,45 +292,55 @@ lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& s
}
lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
- SyntheticChildrenFrontEnd(*valobj_sp.get()),
+SyntheticChildrenFrontEnd(*valobj_sp),
m_exe_ctx_ref(),
m_ptr_size(8),
- m_data_32(NULL),
- m_data_64(NULL)
+m_id_type(),
+m_children()
{
if (valobj_sp)
{
- clang::ASTContext *ast = valobj_sp->GetClangType().GetASTContext();
+ clang::ASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext()->getASTContext();
if (ast)
m_id_type = ClangASTType(ast, ast->ObjCBuiltinIdTy);
+ if (valobj_sp->GetProcessSP())
+ m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize();
}
}
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp) :
+NSArrayMSyntheticFrontEnd(valobj_sp),
+m_data_32(NULL),
+m_data_64(NULL)
+{
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp) :
+NSArrayMSyntheticFrontEnd(valobj_sp),
+m_data_32(NULL),
+m_data_64(NULL)
+{
+}
+
size_t
lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren ()
{
- if (m_data_32)
- return m_data_32->_used;
- if (m_data_64)
- return m_data_64->_used;
- return 0;
+ return GetUsedCount();
}
lldb::ValueObjectSP
lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
{
- if (!m_data_32 && !m_data_64)
- return lldb::ValueObjectSP();
if (idx >= CalculateNumChildren())
return lldb::ValueObjectSP();
- lldb::addr_t object_at_idx = (m_data_32 ? m_data_32->_data : m_data_64->_data);
+ lldb::addr_t object_at_idx = GetDataAddress();
size_t pyhs_idx = idx;
- pyhs_idx += (m_data_32 ? m_data_32->offset : m_data_64->offset);
- if ((m_data_32 ? m_data_32->_size : m_data_64->_size) <= pyhs_idx)
- pyhs_idx -= (m_data_32 ? m_data_32->_size : m_data_64->_size);
+ pyhs_idx += GetOffset();
+ if (GetSize() <= pyhs_idx)
+ pyhs_idx -= GetSize();
object_at_idx += (pyhs_idx * m_ptr_size);
StreamString idx_name;
- idx_name.Printf("[%zu]",idx);
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromAddress(idx_name.GetData(),
object_at_idx,
m_exe_ctx_ref,
@@ -138,7 +350,42 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx
}
bool
-lldb_private::formatters::NSArrayMSyntheticFrontEnd::Update()
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update()
+{
+ m_children.clear();
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ m_ptr_size = 0;
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ Error error;
+ error.Clear();
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return false;
+ m_ptr_size = process_sp->GetAddressByteSize();
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ if (m_ptr_size == 4)
+ {
+ m_data_32 = new DataDescriptor_32();
+ process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
+ }
+ else
+ {
+ m_data_64 = new DataDescriptor_64();
+ process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
+ }
+ if (error.Fail())
+ return false;
+ return false;
+}
+
+bool
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update()
{
m_children.clear();
ValueObjectSP valobj_sp = m_backend.GetSP();
@@ -181,8 +428,6 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren ()
size_t
lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
{
- if (!m_data_32 && !m_data_64)
- return UINT32_MAX;
const char* item_name = name.GetCString();
uint32_t idx = ExtractIndexFromString(item_name);
if (idx < UINT32_MAX && idx >= CalculateNumChildren())
@@ -190,7 +435,87 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (co
return idx;
}
-lldb_private::formatters::NSArrayMSyntheticFrontEnd::~NSArrayMSyntheticFrontEnd ()
+lldb::addr_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress ()
+{
+ if (!m_data_32 && !m_data_64)
+ return LLDB_INVALID_ADDRESS;
+ return m_data_32 ? m_data_32->_data :
+ m_data_64->_data;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->_used :
+ m_data_64->_used;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->_offset :
+ m_data_64->_offset;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->_size :
+ m_data_64->_size;
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::~NSArrayMSyntheticFrontEnd_109 ()
+{
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+}
+
+lldb::addr_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress ()
+{
+ if (!m_data_32 && !m_data_64)
+ return LLDB_INVALID_ADDRESS;
+ return m_data_32 ? m_data_32->_data :
+ m_data_64->_data;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->_used :
+ m_data_64->_used;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->_offset :
+ m_data_64->_offset;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->_size :
+ m_data_64->_size;
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::~NSArrayMSyntheticFrontEnd_1010 ()
{
delete m_data_32;
m_data_32 = NULL;
@@ -278,7 +603,7 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx
if (error.Fail())
return lldb::ValueObjectSP();
StreamString idx_name;
- idx_name.Printf("[%zu]",idx);
+ 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);
m_children.push_back(retval_sp);
return retval_sp;
@@ -286,14 +611,20 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx
SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
+ if (!valobj_sp)
+ return nullptr;
+
lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
if (!process_sp)
return NULL;
- ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+ AppleObjCRuntime *runtime = (AppleObjCRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
if (!runtime)
return NULL;
- if (!valobj_sp->IsPointerType())
+ ClangASTType valobj_type(valobj_sp->GetClangType());
+ Flags flags(valobj_type.GetTypeInfo());
+
+ if (flags.IsClear(ClangASTType::eTypeIsPointer))
{
Error error;
valobj_sp = valobj_sp->AddressOf(error);
@@ -317,7 +648,10 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCre
}
else if (!strcmp(class_name,"__NSArrayM"))
{
- return (new NSArrayMSyntheticFrontEnd(valobj_sp));
+ if (runtime->GetFoundationVersion() >= 1100)
+ return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp));
+ else
+ return (new NSArrayMSyntheticFrontEnd_109(valobj_sp));
}
else
{
@@ -342,7 +676,7 @@ lldb::ValueObjectSP
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
{
StreamString idx_name;
- idx_name.Printf("[%zu]",idx);
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx);
if (valobj_sp)
valobj_sp->SetName(ConstString(idx_name.GetData()));
diff --git a/source/DataFormatters/NSDictionary.cpp b/source/DataFormatters/NSDictionary.cpp
index f53004df5c5f..ddd1e2e7ca90 100644
--- a/source/DataFormatters/NSDictionary.cpp
+++ b/source/DataFormatters/NSDictionary.cpp
@@ -210,9 +210,9 @@ lldb::ValueObjectSP
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
{
StreamString idx_name;
- idx_name.Printf("[%zu]",idx);
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
StreamString key_fetcher_expr;
- key_fetcher_expr.Printf("(id)[(NSArray*)[(id)0x%" PRIx64 " allKeys] objectAtIndex:%zu]",m_backend.GetPointerValue(),idx);
+ key_fetcher_expr.Printf("(id)[(NSArray*)[(id)0x%" PRIx64 " allKeys] objectAtIndex:%" PRIu64 "]", m_backend.GetPointerValue(), (uint64_t)idx);
StreamString value_fetcher_expr;
value_fetcher_expr.Printf("(id)[(id)0x%" PRIx64 " objectForKey:(%s)]",m_backend.GetPointerValue(),key_fetcher_expr.GetData());
StreamString object_fetcher_expr;
@@ -220,7 +220,9 @@ lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIn
lldb::ValueObjectSP child_sp;
EvaluateExpressionOptions options;
options.SetKeepInMemory(true);
- m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), m_backend.GetFrameSP().get(), child_sp,
+ m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(),
+ GetViableFrame(m_backend.GetTargetSP().get()),
+ child_sp,
options);
if (child_sp)
child_sp->SetName(ConstString(idx_name.GetData()));
@@ -403,7 +405,7 @@ lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_
}
StreamString idx_name;
- idx_name.Printf("[%zu]",idx);
+ 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);
}
@@ -567,7 +569,7 @@ lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_
}
StreamString idx_name;
- idx_name.Printf("[%zu]",idx);
+ 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);
}
diff --git a/source/DataFormatters/NSSet.cpp b/source/DataFormatters/NSSet.cpp
index e6fe2a34a67b..3c7c003ed95a 100644
--- a/source/DataFormatters/NSSet.cpp
+++ b/source/DataFormatters/NSSet.cpp
@@ -305,7 +305,7 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
}
StreamString idx_name;
- idx_name.Printf("[%zu]",idx);
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
DataExtractor data(buffer.GetBytes(),
buffer.GetByteSize(),
@@ -473,7 +473,7 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
}
StreamString idx_name;
- idx_name.Printf("[%zu]",idx);
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
DataExtractor data(buffer.GetBytes(),
buffer.GetByteSize(),
@@ -519,7 +519,7 @@ lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetChildAtIndex (size_t
if (retval_sp)
{
StreamString idx_name;
- idx_name.Printf("[%zu]",idx);
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
retval_sp->SetName(ConstString(idx_name.GetData()));
}
m_children[idx] = retval_sp;
diff --git a/source/DataFormatters/TypeFormat.cpp b/source/DataFormatters/TypeFormat.cpp
index a72f551c741f..0c62daf87bbc 100644
--- a/source/DataFormatters/TypeFormat.cpp
+++ b/source/DataFormatters/TypeFormat.cpp
@@ -38,6 +38,9 @@ m_my_revision(0)
{
}
+TypeFormatImpl::~TypeFormatImpl ()
+{
+}
TypeFormatImpl_Format::TypeFormatImpl_Format (lldb::Format f,
const TypeFormatImpl::Flags& flags) :
@@ -46,6 +49,10 @@ m_format (f)
{
}
+TypeFormatImpl_Format::~TypeFormatImpl_Format ()
+{
+}
+
bool
TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
std::string& dest) const
@@ -64,7 +71,10 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
const RegisterInfo *reg_info = value.GetRegisterInfo();
if (reg_info)
{
- valobj->GetData(data);
+ Error error;
+ valobj->GetData(data, error);
+ if (error.Fail())
+ return false;
StreamString reg_sstr;
data.Dump (&reg_sstr,
@@ -105,7 +115,12 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
}
}
else
- valobj->GetData(data);
+ {
+ Error error;
+ valobj->GetData(data, error);
+ if (error.Fail())
+ return false;
+ }
StreamString sstr;
clang_type.DumpTypeValue (&sstr, // The stream to use for display
@@ -154,6 +169,10 @@ m_types()
{
}
+TypeFormatImpl_EnumType::~TypeFormatImpl_EnumType ()
+{
+}
+
bool
TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj,
std::string& dest) const
@@ -203,7 +222,10 @@ TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj,
if (valobj_enum_type.IsValid() == false)
return false;
DataExtractor data;
- valobj->GetData(data);
+ Error error;
+ valobj->GetData(data, error);
+ if (error.Fail())
+ return false;
ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
StreamString sstr;
valobj_enum_type.DumpTypeValue(&sstr,
diff --git a/source/DataFormatters/TypeSummary.cpp b/source/DataFormatters/TypeSummary.cpp
index 4c75b4b87d03..e5d80174c3cc 100644
--- a/source/DataFormatters/TypeSummary.cpp
+++ b/source/DataFormatters/TypeSummary.cpp
@@ -69,7 +69,7 @@ StringSummaryFormat::FormatObject (ValueObject *valobj,
if (IsOneLiner())
{
ValueObjectPrinter printer(valobj,&s,DumpValueObjectOptions());
- printer.PrintChildrenOneLiner(HideNames());
+ printer.PrintChildrenOneLiner(HideNames(valobj));
retval.assign(s.GetData());
return true;
}
@@ -95,12 +95,12 @@ StringSummaryFormat::GetDescription ()
sstr.Printf ("`%s`%s%s%s%s%s%s%s", m_format.c_str(),
Cascades() ? "" : " (not cascading)",
- !DoesPrintChildren() ? "" : " (show children)",
- !DoesPrintValue() ? " (hide value)" : "",
+ !DoesPrintChildren(nullptr) ? "" : " (show children)",
+ !DoesPrintValue(nullptr) ? " (hide value)" : "",
IsOneLiner() ? " (one-line printout)" : "",
SkipsPointers() ? " (skip pointers)" : "",
SkipsReferences() ? " (skip references)" : "",
- HideNames() ? " (hide member names)" : "");
+ HideNames(nullptr) ? " (hide member names)" : "");
return sstr.GetString();
}
@@ -129,14 +129,15 @@ std::string
CXXFunctionSummaryFormat::GetDescription ()
{
StreamString sstr;
- sstr.Printf ("`%s (%p) `%s%s%s%s%s%s%s", m_description.c_str(),m_impl,
+ sstr.Printf ("`%s (%p) `%s%s%s%s%s%s%s", m_description.c_str(),
+ static_cast<void*>(&m_impl),
Cascades() ? "" : " (not cascading)",
- !DoesPrintChildren() ? "" : " (show children)",
- !DoesPrintValue() ? " (hide value)" : "",
+ !DoesPrintChildren(nullptr) ? "" : " (show children)",
+ !DoesPrintValue(nullptr) ? " (hide value)" : "",
IsOneLiner() ? " (one-line printout)" : "",
SkipsPointers() ? " (skip pointers)" : "",
SkipsReferences() ? " (skip references)" : "",
- HideNames() ? " (hide member names)" : "");
+ HideNames(nullptr) ? " (hide member names)" : "");
return sstr.GetString();
}
@@ -198,12 +199,12 @@ ScriptSummaryFormat::GetDescription ()
{
StreamString sstr;
sstr.Printf ("%s%s%s%s%s%s%s\n%s", Cascades() ? "" : " (not cascading)",
- !DoesPrintChildren() ? "" : " (show children)",
- !DoesPrintValue() ? " (hide value)" : "",
+ !DoesPrintChildren(nullptr) ? "" : " (show children)",
+ !DoesPrintValue(nullptr) ? " (hide value)" : "",
IsOneLiner() ? " (one-line printout)" : "",
SkipsPointers() ? " (skip pointers)" : "",
SkipsReferences() ? " (skip references)" : "",
- HideNames() ? " (hide member names)" : "",
+ HideNames(nullptr) ? " (hide member names)" : "",
m_python_script.c_str());
return sstr.GetString();
diff --git a/source/DataFormatters/TypeSynthetic.cpp b/source/DataFormatters/TypeSynthetic.cpp
index 972be486b783..3949673a4be8 100644
--- a/source/DataFormatters/TypeSynthetic.cpp
+++ b/source/DataFormatters/TypeSynthetic.cpp
@@ -57,9 +57,9 @@ CXXSyntheticChildren::GetDescription()
Cascades() ? "" : " (not cascading)",
SkipsPointers() ? " (skip pointers)" : "",
SkipsReferences() ? " (skip references)" : "",
- m_create_callback,
+ reinterpret_cast<void*>(reinterpret_cast<intptr_t>(m_create_callback)),
m_description.c_str());
-
+
return sstr.GetString();
}
diff --git a/source/DataFormatters/ValueObjectPrinter.cpp b/source/DataFormatters/ValueObjectPrinter.cpp
index 944d6d2d13a9..65e5e3f45823 100644
--- a/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/source/DataFormatters/ValueObjectPrinter.cpp
@@ -222,7 +222,11 @@ 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(m_valobj->GetQualifiedTypeName());
+ ConstString qualified_type_name;
+ if (options.m_be_raw)
+ qualified_type_name = m_valobj->GetQualifiedTypeName();
+ else
+ qualified_type_name = m_valobj->GetDisplayTypeName();
if (qualified_type_name)
m_stream->Printf("(%s) ", qualified_type_name.GetCString());
else
@@ -341,7 +345,7 @@ ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed,
// the value if this thing is nil
// (but show the value if the user passes a format explicitly)
TypeSummaryImpl* entry = GetSummaryFormatter();
- if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue() || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value)
+ if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value)
{
m_stream->Printf(" %s", m_value.c_str());
value_printed = true;
@@ -426,7 +430,7 @@ ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
TypeSummaryImpl* entry = GetSummaryFormatter();
- return (!entry || entry->DoesPrintChildren() || m_summary.empty());
+ return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty());
}
return false;
}
diff --git a/source/Expression/ASTResultSynthesizer.cpp b/source/Expression/ASTResultSynthesizer.cpp
index 76c2577af533..2f14721100bc 100644
--- a/source/Expression/ASTResultSynthesizer.cpp
+++ b/source/Expression/ASTResultSynthesizer.cpp
@@ -40,7 +40,7 @@ ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough,
{
if (!m_passthrough)
return;
-
+
m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
}
@@ -49,10 +49,10 @@ ASTResultSynthesizer::~ASTResultSynthesizer()
}
void
-ASTResultSynthesizer::Initialize(ASTContext &Context)
+ASTResultSynthesizer::Initialize(ASTContext &Context)
{
m_ast_context = &Context;
-
+
if (m_passthrough)
m_passthrough->Initialize(Context);
}
@@ -75,11 +75,11 @@ ASTResultSynthesizer::TransformTopLevelDecl(Decl* D)
}
}
-
+
if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D))
{
RecordDecl::decl_iterator decl_iterator;
-
+
for (decl_iterator = linkage_spec_decl->decls_begin();
decl_iterator != linkage_spec_decl->decls_end();
++decl_iterator)
@@ -107,53 +107,53 @@ ASTResultSynthesizer::TransformTopLevelDecl(Decl* D)
}
}
-bool
+bool
ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
{
DeclGroupRef::iterator decl_iterator;
-
+
for (decl_iterator = D.begin();
decl_iterator != D.end();
++decl_iterator)
{
Decl *decl = *decl_iterator;
-
+
TransformTopLevelDecl(decl);
}
-
+
if (m_passthrough)
return m_passthrough->HandleTopLevelDecl(D);
return true;
}
-bool
+bool
ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (!m_sema)
return false;
-
+
FunctionDecl *function_decl = FunDecl;
-
+
if (!function_decl)
return false;
-
+
if (log && log->GetVerbose())
{
std::string s;
raw_string_ostream os(s);
-
+
function_decl->print(os);
-
+
os.flush();
-
+
log->Printf ("Untransformed function AST:\n%s", s.c_str());
}
-
+
Stmt *function_body = function_decl->getBody();
CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
-
+
bool ret = SynthesizeBodyResult (compound_stmt,
function_decl);
@@ -161,14 +161,14 @@ ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl)
{
std::string s;
raw_string_ostream os(s);
-
+
function_decl->print(os);
-
+
os.flush();
-
+
log->Printf ("Transformed function AST:\n%s", s.c_str());
}
-
+
return ret;
}
@@ -176,67 +176,67 @@ bool
ASTResultSynthesizer::SynthesizeObjCMethodResult (ObjCMethodDecl *MethodDecl)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (!m_sema)
return false;
-
+
if (!MethodDecl)
return false;
-
+
if (log && log->GetVerbose())
{
std::string s;
raw_string_ostream os(s);
-
+
MethodDecl->print(os);
-
+
os.flush();
-
+
log->Printf ("Untransformed method AST:\n%s", s.c_str());
}
-
+
Stmt *method_body = MethodDecl->getBody();
-
+
if (!method_body)
return false;
-
+
CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body);
-
+
bool ret = SynthesizeBodyResult (compound_stmt,
MethodDecl);
-
+
if (log && log->GetVerbose())
{
std::string s;
raw_string_ostream os(s);
-
+
MethodDecl->print(os);
-
+
os.flush();
-
+
log->Printf("Transformed method AST:\n%s", s.c_str());
}
-
+
return ret;
}
-bool
-ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
+bool
+ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
DeclContext *DC)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
ASTContext &Ctx(*m_ast_context);
-
+
if (!Body)
return false;
-
+
if (Body->body_empty())
return false;
-
+
Stmt **last_stmt_ptr = Body->body_end() - 1;
Stmt *last_stmt = *last_stmt_ptr;
-
+
while (dyn_cast<NullStmt>(last_stmt))
{
if (last_stmt_ptr != Body->body_begin())
@@ -249,28 +249,28 @@ ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
return false;
}
}
-
+
Expr *last_expr = dyn_cast<Expr>(last_stmt);
-
+
if (!last_expr)
// No auxiliary variable necessary; expression returns void
return true;
-
+
// In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off if that's the
// case.
-
+
do {
ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr);
-
+
if (!implicit_cast)
break;
-
+
if (implicit_cast->getCastKind() != CK_LValueToRValue)
break;
-
+
last_expr = implicit_cast->getSubExpr();
} while (0);
-
+
// is_lvalue is used to record whether the expression returns an assignable Lvalue or an
// Rvalue. This is relevant because they are handled differently.
//
@@ -302,7 +302,7 @@ ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
//
// - In IR transformations, an instruction is inserted at the beginning of the function to
// dereference the pointer resident in the slot. Reads and writes to $__lldb_expr_result
- // are redirected at that dereferenced version. Guard variables for the static variable
+ // are redirected at that dereferenced version. Guard variables for the static variable
// are excised.
//
// - During materialization, $0 (the result persistent variable) is populated with the location
@@ -310,46 +310,46 @@ ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
//
// - During dematerialization, $0 is ignored.
- bool is_lvalue =
+ bool is_lvalue =
(last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) &&
(last_expr->getObjectKind() == OK_Ordinary);
-
+
QualType expr_qual_type = last_expr->getType();
const clang::Type *expr_type = expr_qual_type.getTypePtr();
-
+
if (!expr_type)
return false;
-
+
if (expr_type->isVoidType())
return true;
-
+
if (log)
{
std::string s = expr_qual_type.getAsString();
-
+
log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str());
}
-
+
clang::VarDecl *result_decl = NULL;
-
+
if (is_lvalue)
{
IdentifierInfo *result_ptr_id;
-
+
if (expr_type->isFunctionType())
result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers
else
result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr");
-
+
m_sema->RequireCompleteType(SourceLocation(), expr_qual_type, clang::diag::err_incomplete_type);
-
+
QualType ptr_qual_type;
if (expr_qual_type->getAs<ObjCObjectType>() != NULL)
ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type);
else
ptr_qual_type = Ctx.getPointerType(expr_qual_type);
-
+
result_decl = VarDecl::Create(Ctx,
DC,
SourceLocation(),
@@ -358,69 +358,69 @@ ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
ptr_qual_type,
NULL,
SC_Static);
-
+
if (!result_decl)
return false;
-
+
ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr);
-
- m_sema->AddInitializerToDecl(result_decl, address_of_expr.take(), true, false);
+
+ m_sema->AddInitializerToDecl(result_decl, address_of_expr.get(), true, false);
}
else
{
IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
-
- result_decl = VarDecl::Create(Ctx,
- DC,
+
+ result_decl = VarDecl::Create(Ctx,
+ DC,
SourceLocation(),
SourceLocation(),
- &result_id,
- expr_qual_type,
- NULL,
+ &result_id,
+ expr_qual_type,
+ NULL,
SC_Static);
-
+
if (!result_decl)
return false;
-
+
m_sema->AddInitializerToDecl(result_decl, last_expr, true, false);
}
-
+
DC->addDecl(result_decl);
-
+
///////////////////////////////
// call AddInitializerToDecl
//
-
+
//m_sema->AddInitializerToDecl(result_decl, last_expr);
-
+
/////////////////////////////////
// call ConvertDeclToDeclGroup
//
-
+
Sema::DeclGroupPtrTy result_decl_group_ptr;
-
+
result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl);
-
+
////////////////////////
// call ActOnDeclStmt
//
-
+
StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(result_decl_group_ptr,
SourceLocation(),
SourceLocation()));
-
+
////////////////////////////////////////////////
// replace the old statement with the new one
//
-
- *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.take());
+
+ *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.get());
return true;
}
void
ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
-{
+{
if (m_passthrough)
m_passthrough->HandleTranslationUnit(Ctx);
}
@@ -429,8 +429,8 @@ void
ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx)
{
typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator;
-
- for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()),
+
+ for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()),
e = TypeDeclIterator(FunDeclCtx->decls_end());
i != e;
++i)
@@ -439,35 +439,35 @@ ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx)
}
}
-void
+void
ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D)
{
if (!D->getIdentifier())
return;
-
+
StringRef name = D->getName();
-
+
if (name.size() == 0 || name[0] != '$')
return;
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
ConstString name_cs(name.str().c_str());
-
+
if (log)
log->Printf ("Recording persistent type %s\n", name_cs.GetCString());
-
- Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(),
+
+ Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(),
m_ast_context,
D);
-
+
if (TypeDecl *TypeDecl_scratch = dyn_cast<TypeDecl>(D_scratch))
m_target.GetPersistentVariables().RegisterPersistentType(name_cs, TypeDecl_scratch);
}
-void
+void
ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
-{
+{
if (m_passthrough)
m_passthrough->HandleTagDeclDefinition(D);
}
@@ -479,15 +479,15 @@ ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
m_passthrough->CompleteTentativeDefinition(D);
}
-void
-ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
+void
+ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
{
if (m_passthrough)
m_passthrough->HandleVTable(RD, DefinitionRequired);
}
void
-ASTResultSynthesizer::PrintStats()
+ASTResultSynthesizer::PrintStats()
{
if (m_passthrough)
m_passthrough->PrintStats();
@@ -497,16 +497,16 @@ void
ASTResultSynthesizer::InitializeSema(Sema &S)
{
m_sema = &S;
-
+
if (m_passthrough_sema)
m_passthrough_sema->InitializeSema(S);
}
-void
-ASTResultSynthesizer::ForgetSema()
+void
+ASTResultSynthesizer::ForgetSema()
{
m_sema = NULL;
-
+
if (m_passthrough_sema)
m_passthrough_sema->ForgetSema();
}
diff --git a/source/Expression/ASTStructExtractor.cpp b/source/Expression/ASTStructExtractor.cpp
index d1f21923deb4..2a8b7bc7d8ec 100644
--- a/source/Expression/ASTStructExtractor.cpp
+++ b/source/Expression/ASTStructExtractor.cpp
@@ -39,7 +39,7 @@ ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
{
if (!m_passthrough)
return;
-
+
m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
}
@@ -48,10 +48,10 @@ ASTStructExtractor::~ASTStructExtractor()
}
void
-ASTStructExtractor::Initialize(ASTContext &Context)
+ASTStructExtractor::Initialize(ASTContext &Context)
{
m_ast_context = &Context;
-
+
if (m_passthrough)
m_passthrough->Initialize(Context);
}
@@ -61,17 +61,17 @@ ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F)
{
if (!F->hasBody())
return;
-
+
Stmt *body_stmt = F->getBody();
CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt);
-
+
if (!body_compound_stmt)
return; // do we have to handle this?
-
+
RecordDecl *struct_decl = NULL;
-
+
StringRef desired_name(m_struct_name.c_str());
-
+
for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), be = body_compound_stmt->body_end();
bi != be;
++bi)
@@ -95,26 +95,26 @@ ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F)
if (struct_decl)
break;
}
-
+
if (!struct_decl)
return;
-
+
const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl));
-
+
if (!struct_layout)
return;
-
- m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits
+
+ m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits
m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8;
m_function.m_return_size = struct_layout->getDataSize().getQuantity() - m_function.m_return_offset;
-
+
for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount();
field_index < num_fields;
++field_index)
{
m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8);
}
-
+
m_function.m_struct_valid = true;
}
@@ -122,11 +122,11 @@ void
ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D)
{
LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
-
+
if (linkage_spec_decl)
{
RecordDecl::decl_iterator decl_iterator;
-
+
for (decl_iterator = linkage_spec_decl->decls_begin();
decl_iterator != linkage_spec_decl->decls_end();
++decl_iterator)
@@ -134,9 +134,9 @@ ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D)
ExtractFromTopLevelDecl(*decl_iterator);
}
}
-
+
FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D);
-
+
if (m_ast_context &&
function_decl &&
!m_function.m_wrapper_function_name.compare(function_decl->getNameAsString().c_str()))
@@ -145,20 +145,20 @@ ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D)
}
}
-bool
+bool
ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D)
{
DeclGroupRef::iterator decl_iterator;
-
+
for (decl_iterator = D.begin();
decl_iterator != D.end();
++decl_iterator)
{
Decl *decl = *decl_iterator;
-
+
ExtractFromTopLevelDecl(decl);
}
-
+
if (m_passthrough)
return m_passthrough->HandleTopLevelDecl(D);
return true;
@@ -166,12 +166,12 @@ ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D)
void
ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx)
-{
+{
if (m_passthrough)
m_passthrough->HandleTranslationUnit(Ctx);
}
-void
+void
ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D)
{
if (m_passthrough)
@@ -185,15 +185,15 @@ ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D)
m_passthrough->CompleteTentativeDefinition(D);
}
-void
-ASTStructExtractor::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
+void
+ASTStructExtractor::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
{
if (m_passthrough)
m_passthrough->HandleVTable(RD, DefinitionRequired);
}
void
-ASTStructExtractor::PrintStats()
+ASTStructExtractor::PrintStats()
{
if (m_passthrough)
m_passthrough->PrintStats();
@@ -204,17 +204,17 @@ ASTStructExtractor::InitializeSema(Sema &S)
{
m_sema = &S;
m_action = reinterpret_cast<Action*>(m_sema);
-
+
if (m_passthrough_sema)
m_passthrough_sema->InitializeSema(S);
}
-void
-ASTStructExtractor::ForgetSema()
+void
+ASTStructExtractor::ForgetSema()
{
m_sema = NULL;
m_action = NULL;
-
+
if (m_passthrough_sema)
m_passthrough_sema->ForgetSema();
}
diff --git a/source/Expression/ClangASTSource.cpp b/source/Expression/ClangASTSource.cpp
index 853d102c5426..d488993b90d7 100644
--- a/source/Expression/ClangASTSource.cpp
+++ b/source/Expression/ClangASTSource.cpp
@@ -25,32 +25,32 @@
using namespace clang;
using namespace lldb_private;
-ClangASTSource::~ClangASTSource()
+ClangASTSource::~ClangASTSource()
{
m_ast_importer->ForgetDestination(m_ast_context);
-
+
// We are in the process of destruction, don't create clang ast context on demand
// by passing false to Target::GetScratchClangASTContext(create_on_demand).
ClangASTContext *scratch_clang_ast_context = m_target->GetScratchClangASTContext(false);
-
+
if (!scratch_clang_ast_context)
return;
-
+
clang::ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext();
-
+
if (!scratch_ast_context)
return;
-
+
if (m_ast_context != scratch_ast_context)
m_ast_importer->ForgetSource(scratch_ast_context, m_ast_context);
}
void
-ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer)
+ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer)
{
if (!m_ast_context)
return;
-
+
m_ast_context->getTranslationUnitDecl()->setHasExternalVisibleStorage();
m_ast_context->getTranslationUnitDecl()->setHasExternalLexicalStorage();
}
@@ -59,33 +59,33 @@ ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer)
bool
ClangASTSource::FindExternalVisibleDeclsByName
(
- const DeclContext *decl_ctx,
+ const DeclContext *decl_ctx,
DeclarationName clang_decl_name
-)
+)
{
if (!m_ast_context)
{
SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
return false;
}
-
+
if (GetImportInProgress())
{
SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
return false;
}
-
+
std::string decl_name (clang_decl_name.getAsString());
// if (m_decl_map.DoingASTImport ())
// return DeclContext::lookup_result();
-//
+//
switch (clang_decl_name.getNameKind()) {
// Normal identifiers.
case DeclarationName::Identifier:
{
clang::IdentifierInfo *identifier_info = clang_decl_name.getAsIdentifierInfo();
-
+
if (!identifier_info ||
identifier_info->getBuiltinID() != 0)
{
@@ -94,27 +94,27 @@ ClangASTSource::FindExternalVisibleDeclsByName
}
}
break;
-
+
// Operator names. Not important for now.
case DeclarationName::CXXOperatorName:
case DeclarationName::CXXLiteralOperatorName:
SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
return false;
-
+
// Using directives found in this context.
// Tell Sema we didn't find any or we'll end up getting asked a *lot*.
case DeclarationName::CXXUsingDirective:
SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
return false;
-
+
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
{
- llvm::SmallVector<NamedDecl*, 1> method_decls;
+ llvm::SmallVector<NamedDecl*, 1> method_decls;
NameSearchContext method_search_context (*this, method_decls, clang_decl_name, decl_ctx);
-
+
FindObjCMethodDecls(method_search_context);
SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, method_decls);
@@ -131,21 +131,21 @@ ClangASTSource::FindExternalVisibleDeclsByName
if (!GetLookupsEnabled())
{
- // Wait until we see a '$' at the start of a name before we start doing
+ // Wait until we see a '$' at the start of a name before we start doing
// any lookups so we can avoid lookup up all of the builtin types.
if (!decl_name.empty() && decl_name[0] == '$')
{
SetLookupsEnabled (true);
}
else
- {
+ {
SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
return false;
}
}
ConstString const_decl_name(decl_name.c_str());
-
+
const char *uniqued_const_decl_name = const_decl_name.GetCString();
if (m_active_lookups.find (uniqued_const_decl_name) != m_active_lookups.end())
{
@@ -157,7 +157,7 @@ ClangASTSource::FindExternalVisibleDeclsByName
// static uint32_t g_depth = 0;
// ++g_depth;
// printf("[%5u] FindExternalVisibleDeclsByName() \"%s\"\n", g_depth, uniqued_const_decl_name);
- llvm::SmallVector<NamedDecl*, 4> name_decls;
+ llvm::SmallVector<NamedDecl*, 4> name_decls;
NameSearchContext name_search_context(*this, name_decls, clang_decl_name, decl_ctx);
FindExternalVisibleDecls(name_search_context);
SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, name_decls);
@@ -168,50 +168,48 @@ ClangASTSource::FindExternalVisibleDeclsByName
void
ClangASTSource::CompleteType (TagDecl *tag_decl)
-{
+{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
-
+
if (log)
{
- log->Printf(" CompleteTagDecl[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s",
- current_id,
- m_ast_context,
- tag_decl,
+ log->Printf(" CompleteTagDecl[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s",
+ current_id, static_cast<void*>(m_ast_context),
+ static_cast<void*>(tag_decl),
tag_decl->getName().str().c_str());
-
+
log->Printf(" CTD[%u] Before:", current_id);
ASTDumper dumper((Decl*)tag_decl);
dumper.ToLog(log, " [CTD] ");
}
-
+
if (!m_ast_importer->CompleteTagDecl (tag_decl))
{
// We couldn't complete the type. Maybe there's a definition
// somewhere else that can be completed.
-
+
if (log)
log->Printf(" CTD[%u] Type could not be completed in the module in which it was first found.", current_id);
-
+
bool found = false;
DeclContext *decl_ctx = tag_decl->getDeclContext();
-
+
if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(decl_ctx))
{
ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context);
-
+
if (log && log->GetVerbose())
- log->Printf(" CTD[%u] Inspecting namespace map %p (%d entries)",
- current_id,
- namespace_map.get(),
- (int)namespace_map->size());
-
+ log->Printf(" CTD[%u] Inspecting namespace map %p (%d entries)",
+ current_id, static_cast<void*>(namespace_map.get()),
+ static_cast<int>(namespace_map->size()));
+
if (!namespace_map)
return;
-
+
for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end();
i != e && !found;
++i)
@@ -221,80 +219,80 @@ ClangASTSource::CompleteType (TagDecl *tag_decl)
current_id,
i->second.GetNamespaceDecl()->getNameAsString().c_str(),
i->first->GetFileSpec().GetFilename().GetCString());
-
+
TypeList types;
-
+
SymbolContext null_sc;
ConstString name(tag_decl->getName().str().c_str());
-
+
i->first->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX, types);
-
+
for (uint32_t ti = 0, te = types.GetSize();
ti != te && !found;
++ti)
{
lldb::TypeSP type = types.GetTypeAtIndex(ti);
-
+
if (!type)
continue;
-
+
ClangASTType clang_type (type->GetClangFullType());
-
+
if (!clang_type)
continue;
-
+
const TagType *tag_type = clang_type.GetQualType()->getAs<TagType>();
-
+
if (!tag_type)
continue;
-
+
TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl());
-
+
if (m_ast_importer->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
found = true;
}
}
}
- else
+ else
{
TypeList types;
-
+
SymbolContext null_sc;
ConstString name(tag_decl->getName().str().c_str());
ClangNamespaceDecl namespace_decl;
-
+
const ModuleList &module_list = m_target->GetImages();
bool exact_match = false;
module_list.FindTypes (null_sc, name, exact_match, UINT32_MAX, types);
-
+
for (uint32_t ti = 0, te = types.GetSize();
ti != te && !found;
++ti)
{
lldb::TypeSP type = types.GetTypeAtIndex(ti);
-
+
if (!type)
continue;
-
+
ClangASTType clang_type (type->GetClangFullType());
-
+
if (!clang_type)
continue;
-
+
const TagType *tag_type = clang_type.GetQualType()->getAs<TagType>();
-
+
if (!tag_type)
continue;
-
+
TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl());
-
+
if (m_ast_importer->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
found = true;
}
}
}
-
+
if (log)
{
log->Printf(" [CTD] After:");
@@ -305,28 +303,46 @@ ClangASTSource::CompleteType (TagDecl *tag_decl)
void
ClangASTSource::CompleteType (clang::ObjCInterfaceDecl *interface_decl)
-{
+{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (log)
{
- log->Printf(" [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing an ObjCInterfaceDecl named %s", m_ast_context, interface_decl->getName().str().c_str());
+ log->Printf(" [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing an ObjCInterfaceDecl named %s",
+ static_cast<void*>(m_ast_context),
+ interface_decl->getName().str().c_str());
log->Printf(" [COID] Before:");
ASTDumper dumper((Decl*)interface_decl);
- dumper.ToLog(log, " [COID] ");
+ dumper.ToLog(log, " [COID] ");
+ }
+
+ Decl *original_decl = NULL;
+ ASTContext *original_ctx = NULL;
+
+ if (m_ast_importer->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx))
+ {
+ if (ObjCInterfaceDecl *original_iface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl))
+ {
+ ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl);
+
+ if (complete_iface_decl && (complete_iface_decl != original_iface_decl))
+ {
+ m_ast_importer->SetDeclOrigin(interface_decl, original_iface_decl);
+ }
+ }
}
-
+
m_ast_importer->CompleteObjCInterfaceDecl (interface_decl);
-
+
if (interface_decl->getSuperClass() &&
interface_decl->getSuperClass() != interface_decl)
CompleteType(interface_decl->getSuperClass());
-
+
if (log)
{
log->Printf(" [COID] After:");
ASTDumper dumper((Decl*)interface_decl);
- dumper.ToLog(log, " [COID] ");
+ dumper.ToLog(log, " [COID] ");
}
}
@@ -334,36 +350,36 @@ clang::ObjCInterfaceDecl *
ClangASTSource::GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl)
{
lldb::ProcessSP process(m_target->GetProcessSP());
-
+
if (!process)
return NULL;
-
+
ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
-
+
if (!language_runtime)
return NULL;
-
+
ConstString class_name(interface_decl->getNameAsString().c_str());
-
+
lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name));
-
+
if (!complete_type_sp)
return NULL;
-
+
TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetClangFullType());
lldb::clang_type_t complete_opaque_type = complete_type.GetOpaqueQualType();
-
+
if (!complete_opaque_type)
return NULL;
-
+
const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr();
const ObjCInterfaceType *complete_interface_type = dyn_cast<ObjCInterfaceType>(complete_clang_type);
-
+
if (!complete_interface_type)
return NULL;
-
+
ObjCInterfaceDecl *complete_iface_decl(complete_interface_type->getDecl());
-
+
return complete_iface_decl;
}
@@ -375,83 +391,82 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
ClangASTMetrics::RegisterLexicalQuery();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
const Decl *context_decl = dyn_cast<Decl>(decl_context);
-
+
if (!context_decl)
return ELR_Failure;
-
+
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
-
+
if (log)
{
if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl))
log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p with %s predicate",
- current_id,
- m_ast_context,
+ current_id, static_cast<void*>(m_ast_context),
context_named_decl->getNameAsString().c_str(),
context_decl->getDeclKindName(),
- context_decl,
+ static_cast<const void*>(context_decl),
(predicate ? "non-null" : "null"));
else if(context_decl)
log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p with %s predicate",
- current_id,
- m_ast_context,
- context_decl->getDeclKindName(),
- context_decl,
+ current_id, static_cast<void*>(m_ast_context),
+ context_decl->getDeclKindName(),
+ static_cast<const void*>(context_decl),
(predicate ? "non-null" : "null"));
else
log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context with %s predicate",
- current_id,
- m_ast_context,
+ current_id, static_cast<const void*>(m_ast_context),
(predicate ? "non-null" : "null"));
}
-
+
Decl *original_decl = NULL;
ASTContext *original_ctx = NULL;
-
+
if (!m_ast_importer->ResolveDeclOrigin(context_decl, &original_decl, &original_ctx))
return ELR_Failure;
-
+
if (log)
- {
- log->Printf(" FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", current_id, original_ctx, original_decl);
+ {
+ log->Printf(" FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:",
+ current_id, static_cast<void*>(original_ctx),
+ static_cast<void*>(original_decl));
ASTDumper(original_decl).ToLog(log, " ");
}
-
+
if (ObjCInterfaceDecl *original_iface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl))
{
ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl);
-
+
if (complete_iface_decl && (complete_iface_decl != original_iface_decl))
{
original_decl = complete_iface_decl;
original_ctx = &complete_iface_decl->getASTContext();
-
+
m_ast_importer->SetDeclOrigin(context_decl, original_iface_decl);
}
}
-
+
if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl))
{
ExternalASTSource *external_source = original_ctx->getExternalSource();
-
+
if (external_source)
external_source->CompleteType (original_tag_decl);
}
-
+
const DeclContext *original_decl_context = dyn_cast<DeclContext>(original_decl);
-
+
if (!original_decl_context)
return ELR_Failure;
-
+
for (TagDecl::decl_iterator iter = original_decl_context->decls_begin();
iter != original_decl_context->decls_end();
++iter)
{
Decl *decl = *iter;
-
+
if (!predicate || predicate(decl->getKind()))
{
if (log)
@@ -462,35 +477,35 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
else
log->Printf(" FELD[%d] Adding lexical %sDecl %s", current_id, decl->getDeclKindName(), ast_dumper.GetCString());
}
-
+
Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, original_ctx, decl);
-
+
if (!copied_decl)
continue;
-
+
if (FieldDecl *copied_field = dyn_cast<FieldDecl>(copied_decl))
{
QualType copied_field_type = copied_field->getType();
-
+
m_ast_importer->RequireCompleteType(copied_field_type);
}
-
+
decls.push_back(copied_decl);
-
+
DeclContext *decl_context_non_const = const_cast<DeclContext *>(decl_context);
-
+
if (copied_decl->getDeclContext() != decl_context)
{
if (copied_decl->getDeclContext()->containsDecl(copied_decl))
copied_decl->getDeclContext()->removeDecl(copied_decl);
copied_decl->setDeclContext(decl_context_non_const);
}
-
+
if (!decl_context_non_const->containsDecl(copied_decl))
decl_context_non_const->addDeclInternal(copied_decl);
}
}
-
+
return ELR_AlreadyLoaded;
}
@@ -498,41 +513,48 @@ void
ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context)
{
assert (m_ast_context);
-
+
ClangASTMetrics::RegisterVisibleQuery();
-
+
const ConstString name(context.m_decl_name.getAsString().c_str());
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
-
+
if (log)
{
if (!context.m_decl_context)
- log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a NULL DeclContext", current_id, m_ast_context, name.GetCString());
+ log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a NULL DeclContext",
+ current_id, static_cast<void*>(m_ast_context),
+ name.GetCString());
else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context))
- log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in '%s'", current_id, m_ast_context, name.GetCString(), context_named_decl->getNameAsString().c_str());
+ log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in '%s'",
+ current_id, static_cast<void*>(m_ast_context),
+ name.GetCString(),
+ context_named_decl->getNameAsString().c_str());
else
- log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a '%s'", current_id, m_ast_context, name.GetCString(), context.m_decl_context->getDeclKindName());
+ log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a '%s'",
+ current_id, static_cast<void*>(m_ast_context),
+ name.GetCString(),
+ context.m_decl_context->getDeclKindName());
}
-
+
context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap);
-
+
if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context))
{
ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context);
-
+
if (log && log->GetVerbose())
- log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)",
- current_id,
- namespace_map.get(),
- (int)namespace_map->size());
-
+ log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)",
+ current_id, static_cast<void*>(namespace_map.get()),
+ static_cast<int>(namespace_map->size()));
+
if (!namespace_map)
return;
-
+
for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end();
i != e;
++i)
@@ -542,7 +564,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context)
current_id,
i->second.GetNamespaceDecl()->getNameAsString().c_str(),
i->first->GetFileSpec().GetFilename().GetCString());
-
+
FindExternalVisibleDecls(context,
i->first,
i->second,
@@ -561,158 +583,158 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context)
else
{
ClangNamespaceDecl namespace_decl;
-
+
if (log)
log->Printf(" CAS::FEVD[%u] Searching the root namespace", current_id);
-
+
FindExternalVisibleDecls(context,
lldb::ModuleSP(),
namespace_decl,
current_id);
}
-
+
if (!context.m_namespace_map->empty())
{
if (log && log->GetVerbose())
- log->Printf(" CAS::FEVD[%u] Registering namespace map %p (%d entries)",
+ log->Printf(" CAS::FEVD[%u] Registering namespace map %p (%d entries)",
current_id,
- context.m_namespace_map.get(),
- (int)context.m_namespace_map->size());
-
+ static_cast<void*>(context.m_namespace_map.get()),
+ static_cast<int>(context.m_namespace_map->size()));
+
NamespaceDecl *clang_namespace_decl = AddNamespace(context, context.m_namespace_map);
-
+
if (clang_namespace_decl)
clang_namespace_decl->setHasExternalVisibleStorage();
}
}
-void
-ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
+void
+ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
lldb::ModuleSP module_sp,
ClangNamespaceDecl &namespace_decl,
unsigned int current_id)
{
assert (m_ast_context);
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
SymbolContextList sc_list;
-
+
const ConstString name(context.m_decl_name.getAsString().c_str());
-
+
const char *name_unique_cstr = name.GetCString();
-
+
static ConstString id_name("id");
static ConstString Class_name("Class");
-
+
if (name == id_name || name == Class_name)
return;
-
+
if (name_unique_cstr == NULL)
return;
-
+
// The ClangASTSource is not responsible for finding $-names.
if (name_unique_cstr[0] == '$')
return;
-
+
if (module_sp && namespace_decl)
{
ClangNamespaceDecl found_namespace_decl;
-
+
SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
-
+
if (symbol_vendor)
{
SymbolContext null_sc;
-
+
found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl);
-
+
if (found_namespace_decl)
{
context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(module_sp, found_namespace_decl));
-
+
if (log)
log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s",
current_id,
- name.GetCString(),
+ name.GetCString(),
module_sp->GetFileSpec().GetFilename().GetCString());
}
}
}
- else
+ else
{
const ModuleList &target_images = m_target->GetImages();
Mutex::Locker modules_locker (target_images.GetMutex());
-
+
for (size_t i = 0, e = target_images.GetSize(); i < e; ++i)
{
lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i);
-
+
if (!image)
continue;
-
+
ClangNamespaceDecl found_namespace_decl;
-
+
SymbolVendor *symbol_vendor = image->GetSymbolVendor();
-
+
if (!symbol_vendor)
continue;
-
+
SymbolContext null_sc;
-
+
found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl);
-
+
if (found_namespace_decl)
{
context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(image, found_namespace_decl));
-
+
if (log)
log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s",
current_id,
- name.GetCString(),
+ name.GetCString(),
image->GetFileSpec().GetFilename().GetCString());
}
}
}
-
- do
+
+ do
{
TypeList types;
SymbolContext null_sc;
const bool exact_match = false;
-
+
if (module_sp && namespace_decl)
module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types);
- else
+ else
m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, types);
-
+
if (types.GetSize())
{
lldb::TypeSP type_sp = types.GetTypeAtIndex(0);
-
+
if (log)
{
const char *name_string = type_sp->GetName().GetCString();
-
- log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s",
- current_id,
- name.GetCString(),
+
+ log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s",
+ current_id,
+ name.GetCString(),
(name_string ? name_string : "<anonymous>"));
}
-
+
ClangASTType full_type = type_sp->GetClangFullType();
ClangASTType copied_clang_type (GuardedCopyType(full_type));
-
+
if (!copied_clang_type)
- {
+ {
if (log)
log->Printf(" CAS::FEVD[%u] - Couldn't export a type",
current_id);
-
+
break;
}
-
+
context.AddTypeDecl(copied_clang_type);
}
else
@@ -720,55 +742,55 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
do
{
// Couldn't find any types elsewhere. Try the Objective-C runtime if one exists.
-
+
lldb::ProcessSP process(m_target->GetProcessSP());
-
+
if (!process)
break;
-
+
ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
-
+
if (!language_runtime)
break;
-
+
TypeVendor *type_vendor = language_runtime->GetTypeVendor();
-
+
if (!type_vendor)
break;
-
+
bool append = false;
uint32_t max_matches = 1;
std::vector <ClangASTType> types;
-
+
if (!type_vendor->FindTypes(name,
append,
max_matches,
types))
break;
-
+
if (log)
- {
+ {
log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\" in the runtime",
current_id,
name.GetCString());
}
-
+
ClangASTType copied_clang_type (GuardedCopyType(types[0]));
-
+
if (!copied_clang_type)
{
if (log)
log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the runtime",
current_id);
-
+
break;
}
-
+
context.AddTypeDecl(copied_clang_type);
}
while(0);
}
-
+
} while(0);
}
@@ -782,7 +804,7 @@ public:
D *decl;
};
-template <class D2, template <class D> class TD, class D1>
+template <class D2, template <class D> class TD, class D1>
TD<D2>
DynCast(TD<D1> source)
{
@@ -792,19 +814,19 @@ DynCast(TD<D1> source)
template <class D = Decl> class DeclFromParser;
template <class D = Decl> class DeclFromUser;
-template <class D> class DeclFromParser : public TaggedASTDecl<D> {
+template <class D> class DeclFromParser : public TaggedASTDecl<D> {
public:
DeclFromParser() : TaggedASTDecl<D>() { }
DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) { }
-
+
DeclFromUser<D> GetOrigin(ClangASTImporter *importer);
};
-template <class D> class DeclFromUser : public TaggedASTDecl<D> {
+template <class D> class DeclFromUser : public TaggedASTDecl<D> {
public:
DeclFromUser() : TaggedASTDecl<D>() { }
DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) { }
-
+
DeclFromParser<D> Import(ClangASTImporter *importer, ASTContext &dest_ctx);
};
@@ -841,7 +863,7 @@ FindObjCMethodDeclsWithOrigin (unsigned int current_id,
clang::ASTContext *original_ctx = &original_interface_decl->getASTContext();
Selector original_selector;
-
+
if (decl_name.isObjCZeroArgSelector())
{
IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString());
@@ -857,59 +879,59 @@ FindObjCMethodDeclsWithOrigin (unsigned int current_id,
else
{
SmallVector<IdentifierInfo *, 4> idents;
-
+
clang::Selector sel = decl_name.getObjCSelector();
-
+
unsigned num_args = sel.getNumArgs();
-
+
for (unsigned i = 0;
i != num_args;
++i)
{
idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i)));
}
-
+
original_selector = original_ctx->Selectors.getSelector(num_args, idents.data());
}
-
+
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])
return false;
-
+
for (NamedDecl *named_decl : result)
{
ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(named_decl);
-
+
if (!result_method)
return false;
-
+
Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method);
-
+
if (!copied_decl)
return false;
-
+
ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);
-
+
if (!copied_method_decl)
return false;
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (log)
{
ASTDumper dumper((Decl*)copied_method_decl);
log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, dumper.GetCString());
}
-
+
context.AddNamedDecl(copied_method_decl);
}
-
+
return true;
}
@@ -917,30 +939,30 @@ void
ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
-
+
const DeclarationName &decl_name(context.m_decl_name);
const DeclContext *decl_ctx(context.m_decl_context);
-
+
const ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl_ctx);
-
+
if (!interface_decl)
return;
-
+
do
{
Decl *original_decl = NULL;
ASTContext *original_ctx = NULL;
-
+
m_ast_importer->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx);
-
+
if (!original_decl)
break;
-
+
ObjCInterfaceDecl *original_interface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl);
-
+
if (FindObjCMethodDeclsWithOrigin(current_id,
context,
original_interface_decl,
@@ -949,9 +971,9 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
"at origin"))
return; // found it, no need to look any further
} while (0);
-
+
StreamString ss;
-
+
if (decl_name.isObjCZeroArgSelector())
{
ss.Printf("%s", decl_name.getAsString().c_str());
@@ -961,234 +983,232 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
ss.Printf("%s", decl_name.getAsString().c_str());
}
else
- {
+ {
clang::Selector sel = decl_name.getObjCSelector();
-
+
for (unsigned i = 0, e = sel.getNumArgs();
i != e;
++i)
{
llvm::StringRef r = sel.getNameForSlot(i);
- ss.Printf("%s:", r.str().c_str());
+ ss.Printf("%s:", r.str().c_str());
}
- }
+ }
ss.Flush();
-
+
if (strstr(ss.GetData(), "$__lldb"))
return; // we don't need any results
-
+
ConstString selector_name(ss.GetData());
-
+
if (log)
log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p for selector [%s %s]",
- current_id,
- m_ast_context,
- interface_decl->getNameAsString().c_str(),
+ current_id, static_cast<void*>(m_ast_context),
+ interface_decl->getNameAsString().c_str(),
selector_name.AsCString());
SymbolContextList sc_list;
-
+
const bool include_symbols = false;
const bool include_inlines = false;
const bool append = false;
-
+
std::string interface_name = interface_decl->getNameAsString();
-
+
do
{
StreamString ms;
ms.Printf("-[%s %s]", interface_name.c_str(), selector_name.AsCString());
ms.Flush();
ConstString instance_method_name(ms.GetData());
-
+
m_target->GetImages().FindFunctions(instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list);
-
+
if (sc_list.GetSize())
break;
-
+
ms.Clear();
ms.Printf("+[%s %s]", interface_name.c_str(), selector_name.AsCString());
ms.Flush();
ConstString class_method_name(ms.GetData());
-
+
m_target->GetImages().FindFunctions(class_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list);
-
+
if (sc_list.GetSize())
break;
-
+
// Fall back and check for methods in categories. If we find methods this way, we need to check that they're actually in
// categories on the desired class.
-
+
SymbolContextList candidate_sc_list;
-
+
m_target->GetImages().FindFunctions(selector_name, lldb::eFunctionNameTypeSelector, include_symbols, include_inlines, append, candidate_sc_list);
-
+
for (uint32_t ci = 0, ce = candidate_sc_list.GetSize();
ci != ce;
++ci)
{
SymbolContext candidate_sc;
-
+
if (!candidate_sc_list.GetContextAtIndex(ci, candidate_sc))
continue;
-
+
if (!candidate_sc.function)
continue;
-
+
const char *candidate_name = candidate_sc.function->GetName().AsCString();
-
+
const char *cursor = candidate_name;
-
+
if (*cursor != '+' && *cursor != '-')
continue;
-
+
++cursor;
-
+
if (*cursor != '[')
continue;
-
+
++cursor;
-
+
size_t interface_len = interface_name.length();
-
+
if (strncmp(cursor, interface_name.c_str(), interface_len))
continue;
-
+
cursor += interface_len;
-
+
if (*cursor == ' ' || *cursor == '(')
sc_list.Append(candidate_sc);
}
}
while (0);
-
+
if (sc_list.GetSize())
{
// We found a good function symbol. Use that.
-
+
for (uint32_t i = 0, e = sc_list.GetSize();
i != e;
++i)
{
SymbolContext sc;
-
+
if (!sc_list.GetContextAtIndex(i, sc))
continue;
-
+
if (!sc.function)
continue;
-
+
DeclContext *function_ctx = sc.function->GetClangDeclContext();
-
+
if (!function_ctx)
continue;
-
+
ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(function_ctx);
-
+
if (!method_decl)
continue;
-
+
ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface();
-
+
if (!found_interface_decl)
continue;
-
+
if (found_interface_decl->getName() == interface_decl->getName())
{
Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl);
-
+
if (!copied_decl)
continue;
-
+
ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);
-
+
if (!copied_method_decl)
continue;
-
+
if (log)
{
ASTDumper dumper((Decl*)copied_method_decl);
log->Printf(" CAS::FOMD[%d] found (in symbols) %s", current_id, dumper.GetCString());
}
-
+
context.AddNamedDecl(copied_method_decl);
}
}
-
+
return;
}
-
+
// Try the debug information.
-
+
do
{
ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast<ObjCInterfaceDecl*>(interface_decl));
-
+
if (!complete_interface_decl)
break;
-
+
// We found the complete interface. The runtime never needs to be queried in this scenario.
-
+
DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_decl);
-
+
if (complete_interface_decl == interface_decl)
break; // already checked this one
-
+
if (log)
log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
- current_id,
- complete_interface_decl,
- &complete_iface_decl->getASTContext());
-
+ current_id, static_cast<void*>(complete_interface_decl),
+ static_cast<void*>(&complete_iface_decl->getASTContext()));
+
FindObjCMethodDeclsWithOrigin(current_id,
context,
complete_interface_decl,
m_ast_context,
m_ast_importer,
"in debug info");
-
+
return;
}
while (0);
-
+
do
{
// Check the runtime only if the debug information didn't have a complete interface.
-
+
lldb::ProcessSP process(m_target->GetProcessSP());
-
+
if (!process)
break;
-
+
ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
-
+
if (!language_runtime)
break;
-
+
TypeVendor *type_vendor = language_runtime->GetTypeVendor();
-
+
if (!type_vendor)
break;
-
+
ConstString interface_name(interface_decl->getNameAsString().c_str());
bool append = false;
uint32_t max_matches = 1;
std::vector <ClangASTType> types;
-
+
if (!type_vendor->FindTypes(interface_name,
append,
max_matches,
types))
break;
-
+
const clang::Type *runtime_clang_type = QualType::getFromOpaquePtr(types[0].GetOpaqueQualType()).getTypePtr();
-
+
const ObjCInterfaceType *runtime_interface_type = dyn_cast<ObjCInterfaceType>(runtime_clang_type);
-
+
if (!runtime_interface_type)
break;
-
+
ObjCInterfaceDecl *runtime_interface_decl = runtime_interface_type->getDecl();
-
+
FindObjCMethodDeclsWithOrigin(current_id,
context,
runtime_interface_decl,
@@ -1200,7 +1220,7 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
}
static bool
-FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id,
+FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id,
NameSearchContext &context,
clang::ASTContext &ast_context,
ClangASTImporter *ast_importer,
@@ -1210,15 +1230,15 @@ FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id,
if (origin_iface_decl.IsInvalid())
return false;
-
+
std::string name_str = context.m_decl_name.getAsString();
StringRef name(name_str.c_str());
IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name));
-
+
DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier));
-
+
bool found = false;
-
+
if (origin_property_decl.IsValid())
{
DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(ast_importer, ast_context));
@@ -1229,14 +1249,14 @@ FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id,
ASTDumper dumper((Decl*)parser_property_decl.decl);
log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
}
-
+
context.AddNamedDecl(parser_property_decl.decl);
found = true;
}
}
-
+
DeclFromUser<ObjCIvarDecl> origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier));
-
+
if (origin_ivar_decl.IsValid())
{
DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(ast_importer, ast_context));
@@ -1247,12 +1267,12 @@ FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id,
ASTDumper dumper((Decl*)parser_ivar_decl.decl);
log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
}
-
+
context.AddNamedDecl(parser_ivar_decl.decl);
found = true;
}
}
-
+
return found;
}
@@ -1263,109 +1283,107 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
-
+
DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context));
DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer));
ConstString class_name(parser_iface_decl->getNameAsString().c_str());
-
+
if (log)
log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'",
- current_id,
- m_ast_context,
- parser_iface_decl->getNameAsString().c_str(),
+ current_id, static_cast<void*>(m_ast_context),
+ parser_iface_decl->getNameAsString().c_str(),
context.m_decl_name.getAsString().c_str());
-
- if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
- context,
- *m_ast_context,
- m_ast_importer,
+
+ if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
+ context,
+ *m_ast_context,
+ m_ast_importer,
origin_iface_decl))
return;
-
+
if (log)
log->Printf("CAS::FOPD[%d] couldn't find the property on origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching elsewhere...",
- current_id,
- origin_iface_decl.decl,
- &origin_iface_decl->getASTContext());
-
+ current_id, static_cast<const void*>(origin_iface_decl.decl),
+ static_cast<void*>(&origin_iface_decl->getASTContext()));
+
SymbolContext null_sc;
TypeList type_list;
-
+
do
{
ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast<ObjCInterfaceDecl*>(parser_iface_decl.decl));
-
+
if (!complete_interface_decl)
break;
-
+
// We found the complete interface. The runtime never needs to be queried in this scenario.
-
+
DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_decl);
-
+
if (complete_iface_decl.decl == origin_iface_decl.decl)
break; // already checked this one
-
+
if (log)
log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
current_id,
- complete_iface_decl.decl,
- &complete_iface_decl->getASTContext());
-
- FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
- context,
- *m_ast_context,
- m_ast_importer,
+ static_cast<const void*>(complete_iface_decl.decl),
+ static_cast<void*>(&complete_iface_decl->getASTContext()));
+
+ FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
+ context,
+ *m_ast_context,
+ m_ast_importer,
complete_iface_decl);
-
+
return;
}
while(0);
-
+
do
{
// Check the runtime only if the debug information didn't have a complete interface.
-
+
lldb::ProcessSP process(m_target->GetProcessSP());
-
+
if (!process)
return;
-
+
ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
-
+
if (!language_runtime)
return;
-
+
TypeVendor *type_vendor = language_runtime->GetTypeVendor();
-
+
if (!type_vendor)
break;
-
+
bool append = false;
uint32_t max_matches = 1;
std::vector <ClangASTType> types;
-
+
if (!type_vendor->FindTypes(class_name,
append,
max_matches,
types))
break;
-
+
const clang::Type *runtime_clang_type = QualType::getFromOpaquePtr(types[0].GetOpaqueQualType()).getTypePtr();
const ObjCInterfaceType *runtime_interface_type = dyn_cast<ObjCInterfaceType>(runtime_clang_type);
-
+
if (!runtime_interface_type)
break;
-
+
DeclFromUser<const ObjCInterfaceDecl> runtime_iface_decl(runtime_interface_type->getDecl());
-
+
if (log)
log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
current_id,
- runtime_iface_decl.decl,
- &runtime_iface_decl->getASTContext());
-
+ static_cast<const void*>(runtime_iface_decl.decl),
+ static_cast<void*>(&runtime_iface_decl->getASTContext()));
+
if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
context,
*m_ast_context,
@@ -1381,13 +1399,13 @@ typedef llvm::DenseMap <const CXXRecordDecl *, CharUnits> BaseOffsetMap;
template <class D, class O>
static bool
-ImportOffsetMap (llvm::DenseMap <const D*, O> &destination_map,
+ImportOffsetMap (llvm::DenseMap <const D*, O> &destination_map,
llvm::DenseMap <const D*, O> &source_map,
ClangASTImporter *importer,
ASTContext &dest_ctx)
{
typedef llvm::DenseMap <const D*, O> MapType;
-
+
for (typename MapType::iterator fi = source_map.begin(), fe = source_map.end();
fi != fe;
++fi)
@@ -1398,7 +1416,7 @@ ImportOffsetMap (llvm::DenseMap <const D*, O> &destination_map,
return false;
destination_map.insert(std::pair<const D *, O>(parser_decl.decl, fi->second));
}
-
+
return true;
}
@@ -1406,102 +1424,98 @@ template <bool IsVirtual> bool ExtractBaseOffsets (const ASTRecordLayout &record
DeclFromUser<const CXXRecordDecl> &record,
BaseOffsetMap &base_offsets)
{
- for (CXXRecordDecl::base_class_const_iterator
- bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()),
+ for (CXXRecordDecl::base_class_const_iterator
+ bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()),
be = (IsVirtual ? record->vbases_end() : record->bases_end());
bi != be;
++bi)
{
if (!IsVirtual && bi->isVirtual())
continue;
-
+
const clang::Type *origin_base_type = bi->getType().getTypePtr();
const clang::RecordType *origin_base_record_type = origin_base_type->getAs<RecordType>();
-
+
if (!origin_base_record_type)
return false;
-
+
DeclFromUser <RecordDecl> origin_base_record(origin_base_record_type->getDecl());
-
+
if (origin_base_record.IsInvalid())
return false;
-
+
DeclFromUser <CXXRecordDecl> origin_base_cxx_record(DynCast<CXXRecordDecl>(origin_base_record));
-
+
if (origin_base_cxx_record.IsInvalid())
return false;
-
+
CharUnits base_offset;
-
+
if (IsVirtual)
base_offset = record_layout.getVBaseClassOffset(origin_base_cxx_record.decl);
else
base_offset = record_layout.getBaseClassOffset(origin_base_cxx_record.decl);
-
+
base_offsets.insert(std::pair<const CXXRecordDecl *, CharUnits>(origin_base_cxx_record.decl, base_offset));
}
-
+
return true;
}
-
-bool
+
+bool
ClangASTSource::layoutRecordType(const RecordDecl *record,
- uint64_t &size,
+ uint64_t &size,
uint64_t &alignment,
FieldOffsetMap &field_offsets,
BaseOffsetMap &base_offsets,
BaseOffsetMap &virtual_base_offsets)
{
ClangASTMetrics::RegisterRecordLayout();
-
+
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (log)
- {
log->Printf("LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p [name = '%s']",
- current_id,
- m_ast_context,
- record,
+ current_id, static_cast<void*>(m_ast_context),
+ static_cast<const void*>(record),
record->getNameAsString().c_str());
- }
-
-
+
DeclFromParser <const RecordDecl> parser_record(record);
DeclFromUser <const RecordDecl> origin_record(parser_record.GetOrigin(m_ast_importer));
-
+
if (origin_record.IsInvalid())
return false;
-
+
FieldOffsetMap origin_field_offsets;
BaseOffsetMap origin_base_offsets;
BaseOffsetMap origin_virtual_base_offsets;
-
+
ClangASTContext::GetCompleteDecl(&origin_record->getASTContext(), const_cast<RecordDecl*>(origin_record.decl));
-
+
if (!origin_record.decl->getDefinition())
return false;
-
+
const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl));
-
+
int field_idx = 0, field_count = record_layout.getFieldCount();
-
+
for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end();
fi != fe;
++fi)
{
if (field_idx >= field_count)
return false; // Layout didn't go well. Bail out.
-
+
uint64_t field_offset = record_layout.getFieldOffset(field_idx);
-
+
origin_field_offsets.insert(std::pair<const FieldDecl *, uint64_t>(*fi, field_offset));
-
+
field_idx++;
}
-
+
ASTContext &parser_ast_context(record->getASTContext());
DeclFromUser <const CXXRecordDecl> origin_cxx_record(DynCast<const CXXRecordDecl>(origin_record));
@@ -1517,14 +1531,15 @@ ClangASTSource::layoutRecordType(const RecordDecl *record,
!ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer, parser_ast_context) ||
!ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer, parser_ast_context))
return false;
-
+
size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth();
alignment = record_layout.getAlignment().getQuantity() * m_ast_context->getCharWidth();
-
+
if (log)
{
log->Printf("LRT[%u] returned:", current_id);
- log->Printf("LRT[%u] Original = (RecordDecl*)%p", current_id, origin_record.decl);
+ log->Printf("LRT[%u] Original = (RecordDecl*)%p", current_id,
+ static_cast<const void*>(origin_record.decl));
log->Printf("LRT[%u] Size = %" PRId64, current_id, size);
log->Printf("LRT[%u] Alignment = %" PRId64, current_id, alignment);
log->Printf("LRT[%u] Fields:", current_id);
@@ -1533,10 +1548,8 @@ ClangASTSource::layoutRecordType(const RecordDecl *record,
++fi)
{
log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 " bits",
- current_id,
- *fi,
- fi->getNameAsString().c_str(),
- field_offsets[*fi]);
+ current_id, static_cast<void*>(*fi),
+ fi->getNameAsString().c_str(), field_offsets[*fi]);
}
DeclFromParser <const CXXRecordDecl> parser_cxx_record = DynCast<const CXXRecordDecl>(parser_record);
if (parser_cxx_record.IsValid())
@@ -1547,19 +1560,19 @@ ClangASTSource::layoutRecordType(const RecordDecl *record,
++bi)
{
bool is_virtual = bi->isVirtual();
-
+
QualType base_type = bi->getType();
const RecordType *base_record_type = base_type->getAs<RecordType>();
DeclFromParser <RecordDecl> base_record(base_record_type->getDecl());
DeclFromParser <CXXRecordDecl> base_cxx_record = DynCast<CXXRecordDecl>(base_record);
-
+
log->Printf("LRT[%u] %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 " chars",
- current_id,
- (is_virtual ? "Virtual " : ""),
- base_cxx_record.decl,
+ current_id, (is_virtual ? "Virtual " : ""),
+ static_cast<void*>(base_cxx_record.decl),
base_cxx_record.decl->getNameAsString().c_str(),
- (is_virtual ? virtual_base_offsets[base_cxx_record.decl].getQuantity() :
- base_offsets[base_cxx_record.decl].getQuantity()));
+ (is_virtual
+ ? virtual_base_offsets[base_cxx_record.decl].getQuantity()
+ : base_offsets[base_cxx_record.decl].getQuantity()));
}
}
else
@@ -1567,36 +1580,33 @@ ClangASTSource::layoutRecordType(const RecordDecl *record,
log->Printf("LRD[%u] Not a CXXRecord, so no bases", current_id);
}
}
-
+
return true;
}
-void
+void
ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespace_map,
const ConstString &name,
ClangASTImporter::NamespaceMapSP &parent_map) const
{
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (log)
{
if (parent_map && parent_map->size())
log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s in namespace %s",
- current_id,
- m_ast_context,
+ current_id, static_cast<void*>(m_ast_context),
name.GetCString(),
parent_map->begin()->second.GetNamespaceDecl()->getDeclName().getAsString().c_str());
else
log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s",
- current_id,
- m_ast_context,
+ current_id, static_cast<void*>(m_ast_context),
name.GetCString());
}
-
-
+
if (parent_map)
{
for (ClangASTImporter::NamespaceMap::iterator i = parent_map->begin(), e = parent_map->end();
@@ -1604,28 +1614,28 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac
++i)
{
ClangNamespaceDecl found_namespace_decl;
-
+
lldb::ModuleSP module_sp = i->first;
ClangNamespaceDecl module_parent_namespace_decl = i->second;
-
+
SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
-
+
if (!symbol_vendor)
continue;
-
+
SymbolContext null_sc;
-
+
found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &module_parent_namespace_decl);
-
+
if (!found_namespace_decl)
continue;
-
+
namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(module_sp, found_namespace_decl));
-
+
if (log)
log->Printf(" CMN[%u] Found namespace %s in module %s",
current_id,
- name.GetCString(),
+ name.GetCString(),
module_sp->GetFileSpec().GetFilename().GetCString());
}
}
@@ -1633,36 +1643,36 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac
{
const ModuleList &target_images = m_target->GetImages();
Mutex::Locker modules_locker(target_images.GetMutex());
-
+
ClangNamespaceDecl null_namespace_decl;
-
+
for (size_t i = 0, e = target_images.GetSize(); i < e; ++i)
{
lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i);
-
+
if (!image)
continue;
-
+
ClangNamespaceDecl found_namespace_decl;
-
+
SymbolVendor *symbol_vendor = image->GetSymbolVendor();
-
+
if (!symbol_vendor)
continue;
-
+
SymbolContext null_sc;
-
+
found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &null_namespace_decl);
-
+
if (!found_namespace_decl)
continue;
-
+
namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(image, found_namespace_decl));
-
+
if (log)
log->Printf(" CMN[%u] Found namespace %s in module %s",
current_id,
- name.GetCString(),
+ name.GetCString(),
image->GetFileSpec().GetFilename().GetCString());
}
}
@@ -1673,23 +1683,23 @@ ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::Name
{
if (!namespace_decls)
return NULL;
-
+
const ClangNamespaceDecl &namespace_decl = namespace_decls->begin()->second;
-
+
Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, namespace_decl.GetASTContext(), namespace_decl.GetNamespaceDecl());
-
+
if (!copied_decl)
return NULL;
-
+
NamespaceDecl *copied_namespace_decl = dyn_cast<NamespaceDecl>(copied_decl);
-
+
if (!copied_namespace_decl)
return NULL;
-
+
context.m_decls.push_back(copied_namespace_decl);
-
+
m_ast_importer->RegisterNamespaceMap(copied_namespace_decl, namespace_decls);
-
+
return dyn_cast<NamespaceDecl>(copied_decl);
}
@@ -1697,18 +1707,18 @@ ClangASTType
ClangASTSource::GuardedCopyType (const ClangASTType &src_type)
{
ClangASTMetrics::RegisterLLDBImport();
-
+
SetImportInProgress(true);
-
+
QualType copied_qual_type = m_ast_importer->CopyType (m_ast_context, src_type.GetASTContext(), src_type.GetQualType());
-
+
SetImportInProgress(false);
-
+
if (copied_qual_type.getAsOpaquePtr() && copied_qual_type->getCanonicalTypeInternal().isNull())
// this shouldn't happen, but we're hardening because the AST importer seems to be generating bad types
// on occasion.
return ClangASTType();
-
+
return ClangASTType(m_ast_context, copied_qual_type);
}
@@ -1719,39 +1729,39 @@ NameSearchContext::AddVarDecl(const ClangASTType &type)
if (!type.IsValid())
return NULL;
-
+
IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo();
-
+
clang::ASTContext *ast = type.GetASTContext();
clang::NamedDecl *Decl = VarDecl::Create(*ast,
- const_cast<DeclContext*>(m_decl_context),
- SourceLocation(),
+ const_cast<DeclContext*>(m_decl_context),
+ SourceLocation(),
SourceLocation(),
- ii,
+ ii,
type.GetQualType(),
- 0,
+ 0,
SC_Static);
m_decls.push_back(Decl);
-
+
return Decl;
}
clang::NamedDecl *
-NameSearchContext::AddFunDecl (const ClangASTType &type)
+NameSearchContext::AddFunDecl (const ClangASTType &type)
{
assert (type && "Type for variable must be valid!");
-
+
if (!type.IsValid())
return NULL;
if (m_function_types.count(type))
return NULL;
-
+
m_function_types.insert(type);
-
+
QualType qual_type (type.GetQualType());
-
+
clang::ASTContext *ast = type.GetASTContext();
const bool isInlineSpecified = false;
@@ -1773,20 +1783,20 @@ NameSearchContext::AddFunDecl (const ClangASTType &type)
// We have to do more than just synthesize the FunctionDecl. We have to
// synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do
// this, we raid the function's FunctionProtoType for types.
-
+
const FunctionProtoType *func_proto_type = qual_type.getTypePtr()->getAs<FunctionProtoType>();
-
+
if (func_proto_type)
- {
+ {
unsigned NumArgs = func_proto_type->getNumParams();
unsigned ArgIndex;
-
+
SmallVector<ParmVarDecl *, 5> parm_var_decls;
-
+
for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex)
{
QualType arg_qual_type (func_proto_type->getParamType(ArgIndex));
-
+
parm_var_decls.push_back(ParmVarDecl::Create (*ast,
const_cast<DeclContext*>(m_decl_context),
SourceLocation(),
@@ -1797,7 +1807,7 @@ NameSearchContext::AddFunDecl (const ClangASTType &type)
SC_Static,
NULL));
}
-
+
func_decl->setParams(ArrayRef<ParmVarDecl*>(parm_var_decls));
}
else
@@ -1807,9 +1817,9 @@ NameSearchContext::AddFunDecl (const ClangASTType &type)
if (log)
log->Printf("Function type wasn't a FunctionProtoType");
}
-
+
m_decls.push_back(func_decl);
-
+
return func_decl;
}
@@ -1817,13 +1827,13 @@ clang::NamedDecl *
NameSearchContext::AddGenericFunDecl()
{
FunctionProtoType::ExtProtoInfo proto_info;
-
+
proto_info.Variadic = true;
-
+
QualType generic_function_type(m_ast_source.m_ast_context->getFunctionType (m_ast_source.m_ast_context->UnknownAnyTy, // result
ArrayRef<QualType>(), // argument types
proto_info));
-
+
return AddFunDecl(ClangASTType (m_ast_source.m_ast_context, generic_function_type));
}
@@ -1837,32 +1847,32 @@ NameSearchContext::AddTypeDecl(const ClangASTType &clang_type)
if (const TypedefType *typedef_type = llvm::dyn_cast<TypedefType>(qual_type))
{
TypedefNameDecl *typedef_name_decl = typedef_type->getDecl();
-
+
m_decls.push_back(typedef_name_decl);
-
+
return (NamedDecl*)typedef_name_decl;
}
else if (const TagType *tag_type = qual_type->getAs<TagType>())
{
TagDecl *tag_decl = tag_type->getDecl();
-
+
m_decls.push_back(tag_decl);
-
+
return tag_decl;
}
else if (const ObjCObjectType *objc_object_type = qual_type->getAs<ObjCObjectType>())
{
ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface();
-
+
m_decls.push_back((NamedDecl*)interface_decl);
-
+
return (NamedDecl*)interface_decl;
}
}
return NULL;
}
-void
+void
NameSearchContext::AddLookupResult (clang::DeclContextLookupConstResult result)
{
for (clang::NamedDecl *decl : result)
diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp
index 198fde93386e..43c8a5fb1bcb 100644
--- a/source/Expression/ClangExpressionDeclMap.cpp
+++ b/source/Expression/ClangExpressionDeclMap.cpp
@@ -8,11 +8,6 @@
//===----------------------------------------------------------------------===//
#include "lldb/Expression/ClangExpressionDeclMap.h"
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Decl.h"
@@ -68,21 +63,21 @@ ClangExpressionDeclMap::~ClangExpressionDeclMap()
{
// Note: The model is now that the parser's AST context and all associated
// data does not vanish until the expression has been executed. This means
- // that valuable lookup data (like namespaces) doesn't vanish, but
-
+ // that valuable lookup data (like namespaces) doesn't vanish, but
+
DidParse();
DisableStructVars();
}
-bool
+bool
ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx,
Materializer *materializer)
{
ClangASTMetrics::ClearLocalCounters();
-
+
EnableParserVars();
m_parser_vars->m_exe_ctx = exe_ctx;
-
+
Target *target = exe_ctx.GetTargetPtr();
if (exe_ctx.GetFramePtr())
m_parser_vars->m_sym_ctx = exe_ctx.GetFramePtr()->GetSymbolContext(lldb::eSymbolContextEverything);
@@ -98,18 +93,18 @@ ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx,
m_parser_vars->m_sym_ctx.Clear(true);
m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP();
}
-
+
if (target)
{
m_parser_vars->m_persistent_vars = &target->GetPersistentVariables();
-
+
if (!target->GetScratchClangASTContext())
return false;
}
-
+
m_parser_vars->m_target_info = GetTargetInfo();
m_parser_vars->m_materializer = materializer;
-
+
return true;
}
@@ -120,7 +115,7 @@ ClangExpressionDeclMap::DidParse()
if (log)
ClangASTMetrics::DumpCounters(log);
-
+
if (m_parser_vars.get())
{
for (size_t entity_index = 0, num_entities = m_found_entities.GetSize();
@@ -131,7 +126,7 @@ ClangExpressionDeclMap::DidParse()
if (var_sp)
var_sp->DisableParserVars(GetParserID());
}
-
+
for (size_t pvar_index = 0, num_pvars = m_parser_vars->m_persistent_vars->GetSize();
pvar_index < num_pvars;
++pvar_index)
@@ -140,20 +135,20 @@ ClangExpressionDeclMap::DidParse()
if (pvar_sp)
pvar_sp->DisableParserVars(GetParserID());
}
-
+
DisableParserVars();
}
}
// Interface for IRForTarget
-ClangExpressionDeclMap::TargetInfo
+ClangExpressionDeclMap::TargetInfo
ClangExpressionDeclMap::GetTargetInfo()
{
assert (m_parser_vars.get());
-
+
TargetInfo ret;
-
+
ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
Process *process = exe_ctx.GetProcessPtr();
@@ -162,7 +157,7 @@ ClangExpressionDeclMap::GetTargetInfo()
ret.byte_order = process->GetByteOrder();
ret.address_byte_size = process->GetAddressByteSize();
}
- else
+ else
{
Target *target = exe_ctx.GetTargetPtr();
if (target)
@@ -175,61 +170,61 @@ ClangExpressionDeclMap::GetTargetInfo()
return ret;
}
-bool
-ClangExpressionDeclMap::AddPersistentVariable
+bool
+ClangExpressionDeclMap::AddPersistentVariable
(
- const NamedDecl *decl,
- const ConstString &name,
+ const NamedDecl *decl,
+ const ConstString &name,
TypeFromParser parser_type,
bool is_result,
bool is_lvalue
)
{
assert (m_parser_vars.get());
-
+
if (m_parser_vars->m_materializer && is_result)
{
Error err;
-
+
ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
Target *target = exe_ctx.GetTargetPtr();
if (target == NULL)
return false;
-
+
ASTContext *context(target->GetScratchClangASTContext()->getASTContext());
-
+
TypeFromUser user_type(m_ast_importer->DeportType(context,
parser_type.GetASTContext(),
parser_type.GetOpaqueQualType()),
context);
-
+
uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type, is_lvalue, m_keep_result_in_memory, err);
-
+
ClangExpressionVariableSP var_sp = m_found_entities.CreateVariable(exe_ctx.GetBestExecutionContextScope(),
name,
user_type,
m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_target_info.address_byte_size);
-
+
if (!var_sp)
return false;
-
+
var_sp->EnableParserVars(GetParserID());
-
+
ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID());
parser_vars->m_named_decl = decl;
parser_vars->m_parser_type = parser_type;
-
+
var_sp->EnableJITVars(GetParserID());
-
+
ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID());
-
+
jit_vars->m_offset = offset;
-
+
return true;
}
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
Target *target = exe_ctx.GetTargetPtr();
@@ -237,38 +232,38 @@ ClangExpressionDeclMap::AddPersistentVariable
return false;
ASTContext *context(target->GetScratchClangASTContext()->getASTContext());
-
- TypeFromUser user_type(m_ast_importer->DeportType(context,
+
+ TypeFromUser user_type(m_ast_importer->DeportType(context,
parser_type.GetASTContext(),
parser_type.GetOpaqueQualType()),
context);
-
+
if (!user_type.GetOpaqueQualType())
{
if (log)
log->Printf("Persistent variable's type wasn't copied successfully");
return false;
}
-
+
if (!m_parser_vars->m_target_info.IsValid())
return false;
-
+
ClangExpressionVariableSP var_sp = m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx.GetBestExecutionContextScope (),
name,
user_type,
m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_target_info.address_byte_size);
-
+
if (!var_sp)
return false;
-
+
var_sp->m_frozen_sp->SetHasCompleteType();
-
+
if (is_result)
var_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
else
var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist
-
+
if (is_lvalue)
{
var_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
@@ -278,88 +273,87 @@ ClangExpressionDeclMap::AddPersistentVariable
var_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
var_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
}
-
+
if (m_keep_result_in_memory)
{
var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget;
}
-
+
if (log)
log->Printf("Created persistent variable with flags 0x%hx", var_sp->m_flags);
-
+
var_sp->EnableParserVars(GetParserID());
-
+
ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID());
-
+
parser_vars->m_named_decl = decl;
parser_vars->m_parser_type = parser_type;
-
+
return true;
}
-bool
-ClangExpressionDeclMap::AddValueToStruct
+bool
+ClangExpressionDeclMap::AddValueToStruct
(
const NamedDecl *decl,
const ConstString &name,
llvm::Value *value,
size_t size,
- off_t alignment
+ lldb::offset_t alignment
)
{
assert (m_struct_vars.get());
assert (m_parser_vars.get());
-
+
bool is_persistent_variable = false;
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
m_struct_vars->m_struct_laid_out = false;
-
+
if (m_struct_members.GetVariable(decl, GetParserID()))
return true;
-
+
ClangExpressionVariableSP var_sp (m_found_entities.GetVariable(decl, GetParserID()));
-
+
if (!var_sp)
{
var_sp = m_parser_vars->m_persistent_vars->GetVariable(decl, GetParserID());
is_persistent_variable = true;
}
-
+
if (!var_sp)
return false;
-
+
if (log)
log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure",
- decl,
- name.GetCString(),
+ static_cast<const void*>(decl), name.GetCString(),
var_sp->GetName().GetCString());
-
+
// We know entity->m_parser_vars is valid because we used a parser variable
// to find it
-
+
ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID());
parser_vars->m_llvm_value = value;
-
+
if (ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID()))
{
// We already laid this out; do not touch
-
+
if (log)
log->Printf("Already placed at 0x%llx", (unsigned long long)jit_vars->m_offset);
}
-
+
var_sp->EnableJITVars(GetParserID());
-
+
ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID());
jit_vars->m_alignment = alignment;
jit_vars->m_size = size;
-
+
m_struct_members.AddVariable(var_sp);
-
+
if (m_parser_vars->m_materializer)
{
uint32_t offset = 0;
@@ -379,16 +373,16 @@ ClangExpressionDeclMap::AddValueToStruct
else if (parser_vars->m_lldb_var)
offset = m_parser_vars->m_materializer->AddVariable(parser_vars->m_lldb_var, err);
}
-
+
if (!err.Success())
return false;
-
+
if (log)
log->Printf("Placed at 0x%llx", (unsigned long long)offset);
-
+
jit_vars->m_offset = offset; // TODO DoStructLayout() should not change this.
}
-
+
return true;
}
@@ -396,81 +390,81 @@ bool
ClangExpressionDeclMap::DoStructLayout ()
{
assert (m_struct_vars.get());
-
+
if (m_struct_vars->m_struct_laid_out)
return true;
-
+
if (!m_parser_vars->m_materializer)
return false;
-
+
m_struct_vars->m_struct_alignment = m_parser_vars->m_materializer->GetStructAlignment();
m_struct_vars->m_struct_size = m_parser_vars->m_materializer->GetStructByteSize();
m_struct_vars->m_struct_laid_out = true;
return true;
}
-bool ClangExpressionDeclMap::GetStructInfo
+bool ClangExpressionDeclMap::GetStructInfo
(
uint32_t &num_elements,
size_t &size,
- off_t &alignment
+ lldb::offset_t &alignment
)
{
assert (m_struct_vars.get());
-
+
if (!m_struct_vars->m_struct_laid_out)
return false;
-
+
num_elements = m_struct_members.GetSize();
size = m_struct_vars->m_struct_size;
alignment = m_struct_vars->m_struct_alignment;
-
+
return true;
}
-bool
-ClangExpressionDeclMap::GetStructElement
+bool
+ClangExpressionDeclMap::GetStructElement
(
const NamedDecl *&decl,
llvm::Value *&value,
- off_t &offset,
+ lldb::offset_t &offset,
ConstString &name,
uint32_t index
)
{
assert (m_struct_vars.get());
-
+
if (!m_struct_vars->m_struct_laid_out)
return false;
-
+
if (index >= m_struct_members.GetSize())
return false;
-
+
ClangExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index));
-
+
if (!member_sp)
return false;
-
+
ClangExpressionVariable::ParserVars *parser_vars = member_sp->GetParserVars(GetParserID());
ClangExpressionVariable::JITVars *jit_vars = member_sp->GetJITVars(GetParserID());
-
+
if (!parser_vars ||
!jit_vars ||
!member_sp->GetValueObject())
return false;
-
+
decl = parser_vars->m_named_decl;
value = parser_vars->m_llvm_value;
offset = jit_vars->m_offset;
name = member_sp->GetName();
-
+
return true;
}
bool
-ClangExpressionDeclMap::GetFunctionInfo
+ClangExpressionDeclMap::GetFunctionInfo
(
- const NamedDecl *decl,
+ const NamedDecl *decl,
uint64_t &ptr
)
{
@@ -478,14 +472,14 @@ ClangExpressionDeclMap::GetFunctionInfo
if (!entity_sp)
return false;
-
+
// We know m_parser_vars is valid since we searched for the variable by
// its NamedDecl
-
+
ClangExpressionVariable::ParserVars *parser_vars = entity_sp->GetParserVars(GetParserID());
ptr = parser_vars->m_lldb_value.GetScalar().ULongLong();
-
+
return true;
}
@@ -500,7 +494,7 @@ FindCodeSymbolInContext
SymbolContextList temp_sc_list;
if (sym_ctx.module_sp)
sym_ctx.module_sp->FindSymbolsWithNameAndType(name, eSymbolTypeAny, temp_sc_list);
-
+
if (!sc_list.GetSize() && sym_ctx.target_sp)
sym_ctx.target_sp->GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, temp_sc_list);
@@ -527,14 +521,14 @@ FindCodeSymbolInContext
}
bool
-ClangExpressionDeclMap::GetFunctionAddress
+ClangExpressionDeclMap::GetFunctionAddress
(
const ConstString &name,
uint64_t &func_addr
)
{
assert (m_parser_vars.get());
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
Target *target = exe_ctx.GetTargetPtr();
@@ -545,25 +539,25 @@ ClangExpressionDeclMap::GetFunctionAddress
return false;
SymbolContextList sc_list;
-
+
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
+ // We occasionally get debug information in which a const function is reported
// as non-const, so the mangled name is wrong. This is a hack to compensate.
-
+
if (!strncmp(name.GetCString(), "_ZN", 3) &&
strncmp(name.GetCString(), "_ZNK", 4))
{
std::string fixed_scratch("_ZNK");
fixed_scratch.append(name.GetCString() + 3);
ConstString fixed_name(fixed_scratch.c_str());
-
+
if (log)
log->Printf("Failed to find symbols given non-const name %s; trying %s", name.GetCString(), fixed_name.GetCString());
-
+
FindCodeSymbolInContext(fixed_name, m_parser_vars->m_sym_ctx, sc_list);
sc_list_size = sc_list.GetSize();
}
@@ -574,37 +568,25 @@ ClangExpressionDeclMap::GetFunctionAddress
SymbolContext sym_ctx;
sc_list.GetContextAtIndex(i, sym_ctx);
- const Address *func_so_addr = NULL;
- bool is_indirect_function = false;
+ lldb::addr_t callable_load_addr = LLDB_INVALID_ADDRESS;
+
if (sym_ctx.function)
- func_so_addr = &sym_ctx.function->GetAddressRange().GetBaseAddress();
- else if (sym_ctx.symbol)
{
- if (sym_ctx.symbol->GetType() == eSymbolTypeReExported)
- {
- Symbol *reexported_symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target);
- if (reexported_symbol)
- {
- func_so_addr = &reexported_symbol->GetAddress();
- is_indirect_function = reexported_symbol->IsIndirect();
- }
- }
- else
+ const Address func_so_addr = sym_ctx.function->GetAddressRange().GetBaseAddress();
+ if (func_so_addr.IsValid())
{
- func_so_addr = &sym_ctx.symbol->GetAddress();
- is_indirect_function = sym_ctx.symbol->IsIndirect();
+ callable_load_addr = func_so_addr.GetCallableLoadAddress(target, false);
}
}
+ else if (sym_ctx.symbol)
+ {
+ callable_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target);
+ }
- if (func_so_addr && func_so_addr->IsValid())
+ if (callable_load_addr != LLDB_INVALID_ADDRESS)
{
- lldb::addr_t load_addr = func_so_addr->GetCallableLoadAddress (target, is_indirect_function);
-
- if (load_addr != LLDB_INVALID_ADDRESS)
- {
- func_addr = load_addr;
- return true;
- }
+ func_addr = callable_load_addr;
+ return true;
}
}
return false;
@@ -618,12 +600,12 @@ ClangExpressionDeclMap::GetSymbolAddress (Target &target,
lldb_private::Module *module)
{
SymbolContextList sc_list;
-
+
if (module)
module->FindSymbolsWithNameAndType(name, symbol_type, sc_list);
else
target.GetImages().FindSymbolsWithNameAndType(name, symbol_type, sc_list);
-
+
const uint32_t num_matches = sc_list.GetSize();
addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
@@ -631,12 +613,12 @@ ClangExpressionDeclMap::GetSymbolAddress (Target &target,
{
SymbolContext sym_ctx;
sc_list.GetContextAtIndex(i, sym_ctx);
-
+
const Address *sym_address = &sym_ctx.symbol->GetAddress();
-
+
if (!sym_address || !sym_address->IsValid())
continue;
-
+
if (sym_address)
{
switch (sym_ctx.symbol->GetType())
@@ -702,17 +684,17 @@ ClangExpressionDeclMap::GetSymbolAddress (Target &target,
}
}
}
-
+
if (symbol_load_addr == LLDB_INVALID_ADDRESS && process)
{
ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime();
-
+
if (runtime)
{
symbol_load_addr = runtime->LookupRuntimeSymbol(name);
}
}
-
+
return symbol_load_addr;
}
@@ -720,10 +702,10 @@ addr_t
ClangExpressionDeclMap::GetSymbolAddress (const ConstString &name, lldb::SymbolType symbol_type)
{
assert (m_parser_vars.get());
-
+
if (!m_parser_vars->m_exe_ctx.GetTargetPtr())
return false;
-
+
return GetSymbolAddress(m_parser_vars->m_exe_ctx.GetTargetRef(), m_parser_vars->m_exe_ctx.GetProcessPtr(), name, symbol_type);
}
@@ -733,12 +715,12 @@ ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target,
lldb_private::Module *module)
{
SymbolContextList sc_list;
-
+
if (module)
module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
else
target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
-
+
const uint32_t matches = sc_list.GetSize();
for (uint32_t i=0; i<matches; ++i)
{
@@ -748,7 +730,7 @@ ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target,
{
const Symbol *symbol = sym_ctx.symbol;
const Address *sym_address = &symbol->GetAddress();
-
+
if (sym_address && sym_address->IsValid())
{
switch (symbol->GetType())
@@ -790,7 +772,7 @@ ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target,
}
}
break;
-
+
case eSymbolTypeCode: // We already lookup functions elsewhere
case eSymbolTypeVariable:
case eSymbolTypeLocal:
@@ -818,7 +800,7 @@ ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target,
}
}
}
-
+
return NULL;
}
@@ -833,12 +815,12 @@ ClangExpressionDeclMap::FindGlobalVariable
)
{
VariableList vars;
-
+
if (module && namespace_decl)
module->FindGlobalVariables (name, namespace_decl, true, -1, vars);
else
target.GetImages().FindGlobalVariables(name, true, -1, vars);
-
+
if (vars.GetSize())
{
if (type)
@@ -846,7 +828,7 @@ ClangExpressionDeclMap::FindGlobalVariable
for (size_t i = 0; i < vars.GetSize(); ++i)
{
VariableSP var_sp = vars.GetVariableAtIndex(i);
-
+
if (ClangASTContext::AreTypesSame(*type, var_sp->GetType()->GetClangFullType()))
return var_sp;
}
@@ -856,7 +838,7 @@ ClangExpressionDeclMap::FindGlobalVariable
return vars.GetVariableAtIndex(0);
}
}
-
+
return VariableSP();
}
@@ -866,23 +848,23 @@ void
ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context)
{
assert (m_ast_context);
-
+
ClangASTMetrics::RegisterVisibleQuery();
-
+
const ConstString name(context.m_decl_name.getAsString().c_str());
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (GetImportInProgress())
{
if (log && log->GetVerbose())
log->Printf("Ignoring a query during an import");
return;
}
-
+
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
-
+
if (log)
{
if (!context.m_decl_context)
@@ -892,20 +874,19 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context)
else
log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a '%s'", current_id, name.GetCString(), context.m_decl_context->getDeclKindName());
}
-
+
if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context))
{
ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context);
-
+
if (log && log->GetVerbose())
- log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)",
- current_id,
- namespace_map.get(),
+ log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)",
+ current_id, static_cast<void*>(namespace_map.get()),
(int)namespace_map->size());
-
+
if (!namespace_map)
return;
-
+
for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end();
i != e;
++i)
@@ -915,7 +896,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context)
current_id,
i->second.GetNamespaceDecl()->getNameAsString().c_str(),
i->first->GetFileSpec().GetFilename().GetCString());
-
+
FindExternalVisibleDecls(context,
i->first,
i->second,
@@ -925,65 +906,65 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context)
else if (isa<TranslationUnitDecl>(context.m_decl_context))
{
ClangNamespaceDecl namespace_decl;
-
+
if (log)
log->Printf(" CEDM::FEVD[%u] Searching the root namespace", current_id);
-
+
FindExternalVisibleDecls(context,
lldb::ModuleSP(),
namespace_decl,
current_id);
}
-
+
if (!context.m_found.variable)
ClangASTSource::FindExternalVisibleDecls(context);
}
-void
-ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
+void
+ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
lldb::ModuleSP module_sp,
ClangNamespaceDecl &namespace_decl,
unsigned int current_id)
{
assert (m_ast_context);
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
SymbolContextList sc_list;
-
+
const ConstString name(context.m_decl_name.getAsString().c_str());
-
+
const char *name_unique_cstr = name.GetCString();
-
+
if (name_unique_cstr == NULL)
return;
-
+
static ConstString id_name("id");
static ConstString Class_name("Class");
-
+
if (name == id_name || name == Class_name)
return;
-
- // Only look for functions by name out in our symbols if the function
+
+ // Only look for functions by name out in our symbols if the function
// doesn't start with our phony prefix of '$'
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
if (name_unique_cstr[0] == '$' && !namespace_decl)
{
static ConstString g_lldb_class_name ("$__lldb_class");
-
+
if (name == g_lldb_class_name)
{
// Clang is looking for the type of "this"
-
+
if (frame == NULL)
return;
-
+
SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction);
-
+
if (!sym_ctx.function)
return;
-
+
// Get the block that defines the function
Block *function_block = sym_ctx.GetFunctionBlock();
@@ -991,59 +972,59 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
return;
clang::DeclContext *decl_context = function_block->GetClangDeclContext();
-
+
if (!decl_context)
return;
-
+
clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context);
-
+
if (method_decl)
{
clang::CXXRecordDecl *class_decl = method_decl->getParent();
-
+
QualType class_qual_type(class_decl->getTypeForDecl(), 0);
-
+
TypeFromUser class_user_type (class_qual_type.getAsOpaquePtr(),
&class_decl->getASTContext());
-
+
if (log)
{
ASTDumper ast_dumper(class_qual_type);
log->Printf(" CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString());
}
-
+
TypeFromParser class_type = CopyClassType(class_user_type, current_id);
-
+
if (!class_type.IsValid())
return;
-
+
TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo(QualType::getFromOpaquePtr(class_type.GetOpaqueQualType()));
-
+
if (!type_source_info)
return;
-
+
TypedefDecl *typedef_decl = TypedefDecl::Create(*m_ast_context,
m_ast_context->getTranslationUnitDecl(),
SourceLocation(),
SourceLocation(),
context.m_decl_name.getAsIdentifierInfo(),
type_source_info);
-
-
+
+
if (!typedef_decl)
return;
-
+
context.AddNamedDecl(typedef_decl);
-
+
if (method_decl->isInstance())
{
// self is a pointer to the object
-
+
QualType class_pointer_type = method_decl->getASTContext().getPointerType(class_qual_type);
-
+
TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
&method_decl->getASTContext());
-
+
m_struct_vars->m_object_pointer_type = self_user_type;
}
}
@@ -1055,22 +1036,22 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
// scope and use its type.
// FIXME: This code is formally correct, but clang doesn't currently emit DW_AT_object_pointer
// for C++ so it hasn't actually been tested.
-
+
VariableList *vars = frame->GetVariableList(false);
-
+
lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));
-
+
if (this_var &&
this_var->IsInScope(frame) &&
this_var->LocationIsValidForFrame (frame))
{
Type *this_type = this_var->GetType();
-
+
if (!this_type)
return;
-
+
ClangASTType pointee_type = this_type->GetClangForwardType().GetPointeeType();
-
+
if (pointee_type.IsValid())
{
if (log)
@@ -1078,89 +1059,89 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
ASTDumper ast_dumper(this_type->GetClangFullType());
log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
}
-
+
TypeFromUser class_user_type(pointee_type);
AddOneType(context, class_user_type, current_id);
-
-
+
+
TypeFromUser this_user_type(this_type->GetClangFullType());
m_struct_vars->m_object_pointer_type = this_user_type;
return;
}
}
}
-
+
return;
}
-
+
static ConstString g_lldb_objc_class_name ("$__lldb_objc_class");
if (name == g_lldb_objc_class_name)
{
// Clang is looking for the type of "*self"
-
+
if (!frame)
return;
-
+
SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction);
-
+
if (!sym_ctx.function)
return;
-
+
// Get the block that defines the function
Block *function_block = sym_ctx.GetFunctionBlock();
-
+
if (!function_block)
return;
-
+
clang::DeclContext *decl_context = function_block->GetClangDeclContext();
-
+
if (!decl_context)
return;
-
+
clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context);
-
+
if (method_decl)
{
ObjCInterfaceDecl* self_interface = method_decl->getClassInterface();
-
+
if (!self_interface)
return;
-
+
const clang::Type *interface_type = self_interface->getTypeForDecl();
-
+
if (!interface_type)
return; // This is unlikely, but we have seen crashes where this occurred
-
+
TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(),
&method_decl->getASTContext());
-
+
if (log)
{
ASTDumper ast_dumper(interface_type);
log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
}
-
+
AddOneType(context, class_user_type, current_id);
-
+
if (method_decl->isInstanceMethod())
{
// self is a pointer to the object
-
+
QualType class_pointer_type = method_decl->getASTContext().getObjCObjectPointerType(QualType(interface_type, 0));
-
+
TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
&method_decl->getASTContext());
-
+
m_struct_vars->m_object_pointer_type = self_user_type;
}
else
{
// self is a Class pointer
QualType class_type = method_decl->getASTContext().getObjCClassType();
-
+
TypeFromUser self_user_type(class_type.getAsOpaquePtr(),
&method_decl->getASTContext());
-
+
m_struct_vars->m_object_pointer_type = self_user_type;
}
@@ -1172,22 +1153,22 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
// claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a
// method of the class. In that case, just look up the "self" variable in the the current
// scope and use its type.
-
+
VariableList *vars = frame->GetVariableList(false);
-
+
lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
-
+
if (self_var &&
- self_var->IsInScope(frame) &&
+ self_var->IsInScope(frame) &&
self_var->LocationIsValidForFrame (frame))
{
Type *self_type = self_var->GetType();
-
+
if (!self_type)
return;
-
+
ClangASTType self_clang_type = self_type->GetClangFullType();
-
+
if (self_clang_type.IsObjCClassType())
{
return;
@@ -1198,19 +1179,19 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
if (!self_clang_type)
return;
-
+
if (log)
{
ASTDumper ast_dumper(self_type->GetClangFullType());
log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
}
-
+
TypeFromUser class_user_type (self_clang_type);
-
+
AddOneType(context, class_user_type, current_id);
-
+
TypeFromUser self_user_type(self_type->GetClangFullType());
-
+
m_struct_vars->m_object_pointer_type = self_user_type;
return;
}
@@ -1219,66 +1200,66 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
return;
}
-
+
// any other $__lldb names should be weeded out now
if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1))
return;
-
+
do
{
if (!target)
break;
-
+
ClangASTContext *scratch_clang_ast_context = target->GetScratchClangASTContext();
-
+
if (!scratch_clang_ast_context)
break;
-
+
ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext();
-
+
if (!scratch_ast_context)
break;
-
+
TypeDecl *ptype_type_decl = m_parser_vars->m_persistent_vars->GetPersistentType(name);
-
+
if (!ptype_type_decl)
break;
-
+
Decl *parser_ptype_decl = m_ast_importer->CopyDecl(m_ast_context, scratch_ast_context, ptype_type_decl);
-
+
if (!parser_ptype_decl)
break;
-
+
TypeDecl *parser_ptype_type_decl = dyn_cast<TypeDecl>(parser_ptype_decl);
-
+
if (!parser_ptype_type_decl)
break;
-
+
if (log)
log->Printf(" CEDM::FEVD[%u] Found persistent type %s", current_id, name.GetCString());
-
+
context.AddNamedDecl(parser_ptype_type_decl);
} while (0);
-
+
ClangExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name));
-
+
if (pvar_sp)
{
AddOneVariable(context, pvar_sp, current_id);
return;
}
-
+
const char *reg_name(&name.GetCString()[1]);
-
+
if (m_parser_vars->m_exe_ctx.GetRegisterContext())
{
const RegisterInfo *reg_info(m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(reg_name));
-
+
if (reg_info)
{
if (log)
log->Printf(" CEDM::FEVD[%u] Found register %s", current_id, reg_info->name);
-
+
AddOneRegister(context, reg_info, current_id);
}
}
@@ -1288,11 +1269,11 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
ValueObjectSP valobj;
VariableSP var;
Error err;
-
+
if (frame && !namespace_decl)
{
- valobj = frame->GetValueForVariableExpressionPath(name_unique_cstr,
- eNoDynamicValues,
+ valobj = frame->GetValueForVariableExpressionPath(name_unique_cstr,
+ eNoDynamicValues,
StackFrame::eExpressionPathOptionCheckPtrVsMember ||
StackFrame::eExpressionPathOptionsAllowDirectIVarAccess ||
StackFrame::eExpressionPathOptionsNoFragileObjcIvar ||
@@ -1300,7 +1281,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
var,
err);
-
+
// If we found a variable in scope, no need to pull up function names
if (err.Success() && var)
{
@@ -1309,7 +1290,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
return;
}
}
-
+
if (target)
{
var = FindGlobalVariable (*target,
@@ -1317,7 +1298,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
name,
&namespace_decl,
NULL);
-
+
if (var)
{
valobj = ValueObjectVariable::Create(target, var);
@@ -1326,19 +1307,19 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
return;
}
}
-
+
if (!context.m_found.variable)
{
const bool include_inlines = false;
const bool append = false;
-
+
if (namespace_decl && module_sp)
{
const bool include_symbols = false;
module_sp->FindFunctions(name,
&namespace_decl,
- eFunctionNameTypeBase,
+ eFunctionNameTypeBase,
include_symbols,
include_inlines,
append,
@@ -1347,63 +1328,63 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
else if (target && !namespace_decl)
{
const bool include_symbols = true;
-
+
// TODO Fix FindFunctions so that it doesn't return
// instance methods for eFunctionNameTypeBase.
-
+
target->GetImages().FindFunctions(name,
eFunctionNameTypeFull,
include_symbols,
include_inlines,
- append,
+ append,
sc_list);
}
-
+
if (sc_list.GetSize())
{
Symbol *extern_symbol = NULL;
Symbol *non_extern_symbol = NULL;
-
+
for (uint32_t index = 0, num_indices = sc_list.GetSize();
index < num_indices;
++index)
{
SymbolContext sym_ctx;
sc_list.GetContextAtIndex(index, sym_ctx);
-
+
if (sym_ctx.function)
{
clang::DeclContext *decl_ctx = sym_ctx.function->GetClangDeclContext();
-
+
if (!decl_ctx)
continue;
-
+
// Filter out class/instance methods.
if (dyn_cast<clang::ObjCMethodDecl>(decl_ctx))
continue;
if (dyn_cast<clang::CXXMethodDecl>(decl_ctx))
continue;
-
+
AddOneFunction(context, sym_ctx.function, NULL, current_id);
context.m_found.function_with_type_info = true;
context.m_found.function = true;
}
else if (sym_ctx.symbol)
{
- if (sym_ctx.symbol->GetType() == eSymbolTypeReExported)
+ if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target)
{
sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target);
if (sym_ctx.symbol == NULL)
continue;
}
-
+
if (sym_ctx.symbol->IsExternal())
extern_symbol = sym_ctx.symbol;
else
non_extern_symbol = sym_ctx.symbol;
}
}
-
+
if (!context.m_found.function_with_type_info)
{
if (extern_symbol)
@@ -1418,14 +1399,14 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
}
}
}
-
+
if (target && !context.m_found.variable && !namespace_decl)
{
- // We couldn't find a non-symbol variable for this. Now we'll hunt for a generic
+ // We couldn't find a non-symbol variable for this. Now we'll hunt for a generic
// data symbol, and -- if it is found -- treat it as a variable.
-
+
const Symbol *data_symbol = FindGlobalDataSymbol(*target, name);
-
+
if (data_symbol)
{
std::string warning("got name from symbols: ");
@@ -1440,43 +1421,43 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
}
}
-static clang_type_t
-MaybePromoteToBlockPointerType
-(
- ASTContext *ast_context,
- clang_type_t candidate_type
-)
-{
- if (!candidate_type)
- return candidate_type;
-
- QualType candidate_qual_type = QualType::getFromOpaquePtr(candidate_type);
-
- const PointerType *candidate_pointer_type = dyn_cast<PointerType>(candidate_qual_type);
-
- if (!candidate_pointer_type)
- return candidate_type;
-
- QualType pointee_qual_type = candidate_pointer_type->getPointeeType();
-
- const RecordType *pointee_record_type = dyn_cast<RecordType>(pointee_qual_type);
-
- if (!pointee_record_type)
- return candidate_type;
-
- RecordDecl *pointee_record_decl = pointee_record_type->getDecl();
-
- if (!pointee_record_decl->isRecord())
- return candidate_type;
-
- if (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_")))
- return candidate_type;
-
- QualType generic_function_type = ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy);
- QualType block_pointer_type = ast_context->getBlockPointerType(generic_function_type);
-
- return block_pointer_type.getAsOpaquePtr();
-}
+//static clang_type_t
+//MaybePromoteToBlockPointerType
+//(
+// ASTContext *ast_context,
+// clang_type_t candidate_type
+//)
+//{
+// if (!candidate_type)
+// return candidate_type;
+//
+// QualType candidate_qual_type = QualType::getFromOpaquePtr(candidate_type);
+//
+// const PointerType *candidate_pointer_type = dyn_cast<PointerType>(candidate_qual_type);
+//
+// if (!candidate_pointer_type)
+// return candidate_type;
+//
+// QualType pointee_qual_type = candidate_pointer_type->getPointeeType();
+//
+// const RecordType *pointee_record_type = dyn_cast<RecordType>(pointee_qual_type);
+//
+// if (!pointee_record_type)
+// return candidate_type;
+//
+// RecordDecl *pointee_record_decl = pointee_record_type->getDecl();
+//
+// if (!pointee_record_decl->isRecord())
+// return candidate_type;
+//
+// if (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_")))
+// return candidate_type;
+//
+// QualType generic_function_type = ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy);
+// QualType block_pointer_type = ast_context->getBlockPointerType(generic_function_type);
+//
+// return block_pointer_type.getAsOpaquePtr();
+//}
bool
ClangExpressionDeclMap::GetVariableValue (VariableSP &var,
@@ -1485,25 +1466,25 @@ ClangExpressionDeclMap::GetVariableValue (VariableSP &var,
TypeFromParser *parser_type)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
Type *var_type = var->GetType();
-
- if (!var_type)
+
+ if (!var_type)
{
if (log)
log->PutCString("Skipped a definition because it has no type");
return false;
}
-
+
ClangASTType var_clang_type = var_type->GetClangFullType();
-
+
if (!var_clang_type)
{
if (log)
log->PutCString("Skipped a definition because it has no Clang type");
return false;
}
-
+
ASTContext *ast = var_type->GetClangASTContext().getASTContext();
if (!ast)
@@ -1513,25 +1494,16 @@ ClangExpressionDeclMap::GetVariableValue (VariableSP &var,
return false;
}
//var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type);
-
+
DWARFExpression &var_location_expr = var->LocationExpression();
-
- lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
-
- Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
- if (var_location_expr.IsLocationList())
- {
- SymbolContext var_sc;
- var->CalculateSymbolContext (&var_sc);
- loclist_base_load_addr = var_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
- }
+ Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
Error err;
-
+
if (var->GetLocationIsConstantValueData())
{
DataExtractor const_value_extractor;
-
+
if (var_location_expr.GetExpressionData(const_value_extractor))
{
var_location = Value(const_value_extractor.GetDataStart(), const_value_extractor.GetByteSize());
@@ -1544,45 +1516,45 @@ ClangExpressionDeclMap::GetVariableValue (VariableSP &var,
return false;
}
}
-
+
ClangASTType type_to_use = GuardedCopyType(var_clang_type);
-
+
if (!type_to_use)
{
if (log)
log->Printf("Couldn't copy a variable's type into the parser's AST context");
-
+
return false;
}
-
+
if (parser_type)
*parser_type = TypeFromParser(type_to_use);
-
+
if (var_location.GetContextType() == Value::eContextTypeInvalid)
var_location.SetClangType(type_to_use);
-
+
if (var_location.GetValueType() == Value::eValueTypeFileAddress)
{
SymbolContext var_sc;
var->CalculateSymbolContext(&var_sc);
-
+
if (!var_sc.module_sp)
return false;
Address so_addr(var_location.GetScalar().ULongLong(), var_sc.module_sp->GetSectionList());
-
+
lldb::addr_t load_addr = so_addr.GetLoadAddress(target);
-
+
if (load_addr != LLDB_INVALID_ADDRESS)
{
var_location.GetScalar() = load_addr;
var_location.SetValueType(Value::eValueTypeLoadAddress);
}
}
-
+
if (user_type)
*user_type = TypeFromUser(var_clang_type);
-
+
return true;
}
@@ -1590,21 +1562,21 @@ void
ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP var, ValueObjectSP valobj, unsigned int current_id)
{
assert (m_parser_vars.get());
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
TypeFromUser ut;
TypeFromParser pt;
Value var_location;
-
+
if (!GetVariableValue (var, var_location, &ut, &pt))
return;
-
+
clang::QualType parser_opaque_type = QualType::getFromOpaquePtr(pt.GetOpaqueQualType());
-
+
if (parser_opaque_type.isNull())
return;
-
+
if (const clang::Type *parser_type = parser_opaque_type.getTypePtr())
{
if (const TagType *tag_type = dyn_cast<TagType>(parser_type))
@@ -1612,8 +1584,8 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v
if (const ObjCObjectPointerType *objc_object_ptr_type = dyn_cast<ObjCObjectPointerType>(parser_type))
CompleteType(objc_object_ptr_type->getInterfaceDecl());
}
-
-
+
+
bool is_reference = pt.IsReferenceType();
NamedDecl *var_decl = NULL;
@@ -1621,11 +1593,11 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v
var_decl = context.AddVarDecl(pt);
else
var_decl = context.AddVarDecl(pt.GetLValueReferenceType());
-
+
std::string decl_name(context.m_decl_name.getAsString());
ConstString entity_name(decl_name.c_str());
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (valobj));
-
+
assert (entity.get());
entity->EnableParserVars(GetParserID());
ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
@@ -1634,45 +1606,45 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v
parser_vars->m_llvm_value = NULL;
parser_vars->m_lldb_value = var_location;
parser_vars->m_lldb_var = var;
-
+
if (is_reference)
entity->m_flags |= ClangExpressionVariable::EVTypeIsReference;
-
+
if (log)
{
ASTDumper orig_dumper(ut.GetOpaqueQualType());
- ASTDumper ast_dumper(var_decl);
+ ASTDumper ast_dumper(var_decl);
log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", current_id, decl_name.c_str(), ast_dumper.GetCString(), orig_dumper.GetCString());
}
}
void
ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
- ClangExpressionVariableSP &pvar_sp,
+ ClangExpressionVariableSP &pvar_sp,
unsigned int current_id)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
TypeFromUser user_type (pvar_sp->GetTypeFromUser());
-
+
TypeFromParser parser_type (GuardedCopyType(user_type));
-
+
if (!parser_type.GetOpaqueQualType())
{
if (log)
log->Printf(" CEDM::FEVD[%u] Couldn't import type for pvar %s", current_id, pvar_sp->GetName().GetCString());
return;
}
-
+
NamedDecl *var_decl = context.AddVarDecl(parser_type.GetLValueReferenceType());
-
+
pvar_sp->EnableParserVars(GetParserID());
ClangExpressionVariable::ParserVars *parser_vars = pvar_sp->GetParserVars(GetParserID());
parser_vars->m_parser_type = parser_type;
parser_vars->m_named_decl = var_decl;
parser_vars->m_llvm_value = NULL;
parser_vars->m_lldb_value.Clear();
-
+
if (log)
{
ASTDumper ast_dumper(var_decl);
@@ -1681,59 +1653,59 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
}
void
-ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
+ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
const Symbol &symbol,
unsigned int current_id)
{
assert(m_parser_vars.get());
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
if (target == NULL)
return;
ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext();
-
+
TypeFromUser user_type (ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType());
TypeFromParser parser_type (ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType());
NamedDecl *var_decl = context.AddVarDecl(parser_type);
-
+
std::string decl_name(context.m_decl_name.getAsString());
ConstString entity_name(decl_name.c_str());
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (),
- entity_name,
+ entity_name,
user_type,
m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_target_info.address_byte_size));
assert (entity.get());
-
+
entity->EnableParserVars(GetParserID());
ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
const Address &symbol_address = symbol.GetAddress();
lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target);
-
+
//parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType());
parser_vars->m_lldb_value.SetClangType(user_type);
parser_vars->m_lldb_value.GetScalar() = symbol_load_addr;
parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress);
-
+
parser_vars->m_parser_type = parser_type;
parser_vars->m_named_decl = var_decl;
parser_vars->m_llvm_value = NULL;
parser_vars->m_lldb_sym = &symbol;
-
+
if (log)
{
ASTDumper ast_dumper(var_decl);
-
+
log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s", current_id, decl_name.c_str(), ast_dumper.GetCString());
}
}
-bool
+bool
ClangExpressionDeclMap::ResolveUnknownTypes()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -1746,82 +1718,82 @@ ClangExpressionDeclMap::ResolveUnknownTypes()
++index)
{
ClangExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index);
-
+
ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
-
+
if (entity->m_flags & ClangExpressionVariable::EVUnknownType)
{
const NamedDecl *named_decl = parser_vars->m_named_decl;
const VarDecl *var_decl = dyn_cast<VarDecl>(named_decl);
-
+
if (!var_decl)
{
if (log)
log->Printf("Entity of unknown type does not have a VarDecl");
return false;
}
-
+
if (log)
{
ASTDumper ast_dumper(const_cast<VarDecl*>(var_decl));
log->Printf("Variable of unknown type now has Decl %s", ast_dumper.GetCString());
}
-
+
QualType var_type = var_decl->getType();
TypeFromParser parser_type(var_type.getAsOpaquePtr(), &var_decl->getASTContext());
-
+
lldb::clang_type_t copied_type = m_ast_importer->CopyType(scratch_ast_context, &var_decl->getASTContext(), var_type.getAsOpaquePtr());
-
+
if (!copied_type)
- {
+ {
if (log)
log->Printf("ClangExpressionDeclMap::ResolveUnknownType - Couldn't import the type for a variable");
-
+
return (bool) lldb::ClangExpressionVariableSP();
}
-
+
TypeFromUser user_type(copied_type, scratch_ast_context);
-
+
// parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType());
parser_vars->m_lldb_value.SetClangType(user_type);
parser_vars->m_parser_type = parser_type;
-
+
entity->SetClangType(user_type);
-
+
entity->m_flags &= ~(ClangExpressionVariable::EVUnknownType);
}
}
-
+
return true;
}
void
ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context,
- const RegisterInfo *reg_info,
+ const RegisterInfo *reg_info,
unsigned int current_id)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
ClangASTType clang_type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (m_ast_context,
reg_info->encoding,
reg_info->byte_size * 8);
-
+
if (!clang_type)
{
if (log)
log->Printf(" Tried to add a type for %s, but couldn't get one", context.m_decl_name.getAsString().c_str());
return;
}
-
+
TypeFromParser parser_clang_type (clang_type);
-
+
NamedDecl *var_decl = context.AddVarDecl(parser_clang_type);
-
+
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(),
m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_target_info.address_byte_size));
assert (entity.get());
-
+
std::string decl_name(context.m_decl_name.getAsString());
entity->SetName (ConstString (decl_name.c_str()));
entity->SetRegisterInfo (reg_info);
@@ -1832,7 +1804,7 @@ ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context,
parser_vars->m_llvm_value = NULL;
parser_vars->m_lldb_value.Clear();
entity->m_flags |= ClangExpressionVariable::EVBareRegister;
-
+
if (log)
{
ASTDumper ast_dumper(var_decl);
@@ -1847,9 +1819,9 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
unsigned int current_id)
{
assert (m_parser_vars.get());
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
NamedDecl *function_decl = NULL;
const Address *fun_address = NULL;
ClangASTType function_clang_type;
@@ -1859,30 +1831,30 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
if (function)
{
Type *function_type = function->GetType();
-
+
if (!function_type)
{
if (log)
log->PutCString(" Skipped a function because it has no type");
return;
}
-
+
function_clang_type = function_type->GetClangFullType();
-
+
if (!function_clang_type)
{
if (log)
log->PutCString(" Skipped a function because it has no Clang type");
return;
}
-
+
fun_address = &function->GetAddressRange().GetBaseAddress();
-
+
ClangASTType copied_function_type = GuardedCopyType(function_clang_type);
if (copied_function_type)
{
function_decl = context.AddFunDecl(copied_function_type);
-
+
if (!function_decl)
{
if (log)
@@ -1891,7 +1863,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
function_type->GetName().GetCString(),
function_type->GetID());
}
-
+
return;
}
}
@@ -1904,7 +1876,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
function_type->GetName().GetCString(),
function_type->GetID());
}
-
+
return;
}
}
@@ -1920,11 +1892,11 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
log->PutCString(" AddOneFunction called with no function and no symbol");
return;
}
-
+
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
lldb::addr_t load_addr = fun_address->GetCallableLoadAddress(target, is_indirect_function);
-
+
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (),
m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_target_info.address_byte_size));
@@ -1936,7 +1908,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
entity->EnableParserVars(GetParserID());
ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
-
+
if (load_addr != LLDB_INVALID_ADDRESS)
{
parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress);
@@ -1945,25 +1917,25 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
else
{
// We have to try finding a file address.
-
+
lldb::addr_t file_addr = fun_address->GetFileAddress();
-
+
parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress);
parser_vars->m_lldb_value.GetScalar() = file_addr;
}
-
+
parser_vars->m_named_decl = function_decl;
parser_vars->m_llvm_value = NULL;
-
+
if (log)
{
ASTDumper ast_dumper(function_decl);
-
+
StreamString ss;
-
+
fun_address->Dump(&ss, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription);
-
+
log->Printf(" CEDM::FEVD[%u] Found %s function %s (description %s), returned %s",
current_id,
(function ? "specific" : "generic"),
@@ -1978,14 +1950,14 @@ ClangExpressionDeclMap::CopyClassType(TypeFromUser &ut,
unsigned int current_id)
{
ClangASTType copied_clang_type = GuardedCopyType(ut);
-
+
if (!copied_clang_type)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (log)
log->Printf("ClangExpressionDeclMap::CopyClassType - Couldn't import the type");
-
+
return TypeFromParser();
}
@@ -1993,21 +1965,21 @@ ClangExpressionDeclMap::CopyClassType(TypeFromUser &ut,
{
ClangASTType void_clang_type = ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid);
ClangASTType void_ptr_clang_type = void_clang_type.GetPointerType();
-
+
ClangASTType method_type = ClangASTContext::CreateFunctionType (m_ast_context,
void_clang_type,
&void_ptr_clang_type,
1,
false,
copied_clang_type.GetTypeQualifiers());
-
+
const bool is_virtual = false;
const bool is_static = false;
const bool is_inline = false;
const bool is_explicit = false;
const bool is_attr_used = true;
const bool is_artificial = false;
-
+
copied_clang_type.AddMethodToCXXRecordType ("$__lldb_expr",
method_type,
lldb::eAccessPublic,
@@ -2018,26 +1990,26 @@ ClangExpressionDeclMap::CopyClassType(TypeFromUser &ut,
is_attr_used,
is_artificial);
}
-
+
return TypeFromParser(copied_clang_type);
}
-void
-ClangExpressionDeclMap::AddOneType(NameSearchContext &context,
+void
+ClangExpressionDeclMap::AddOneType(NameSearchContext &context,
TypeFromUser &ut,
unsigned int current_id)
{
ClangASTType copied_clang_type = GuardedCopyType(ut);
-
+
if (!copied_clang_type)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
log->Printf("ClangExpressionDeclMap::AddOneType - Couldn't import the type");
-
+
return;
}
-
+
context.AddTypeDecl(copied_clang_type);
}
diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp
index 615f29fd0c76..f32ca3ae216c 100644
--- a/source/Expression/ClangExpressionParser.cpp
+++ b/source/Expression/ClangExpressionParser.cpp
@@ -15,6 +15,7 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
@@ -24,6 +25,9 @@
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Host/File.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
@@ -55,11 +59,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/TargetSelect.h"
-#if defined (USE_STANDARD_JIT)
-#include "llvm/ExecutionEngine/JIT.h"
-#else
#include "llvm/ExecutionEngine/MCJIT.h"
-#endif
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/ErrorHandling.h"
@@ -88,89 +88,8 @@ std::string GetBuiltinIncludePath(const char *Argv0) {
llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING,
"include");
}
-
- return P.str();
-}
-
-
-//===----------------------------------------------------------------------===//
-// Main driver for Clang
-//===----------------------------------------------------------------------===//
-
-static void LLVMErrorHandler(void *UserData, const std::string &Message) {
- DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
-
- Diags.Report(diag::err_fe_error_backend) << Message;
-
- // We cannot recover from llvm errors.
- assert(0);
-}
-static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
- using namespace clang::frontend;
-
- switch (CI.getFrontendOpts().ProgramAction) {
- default:
- llvm_unreachable("Invalid program action!");
-
- case ASTDump: return new ASTDumpAction();
- case ASTPrint: return new ASTPrintAction();
- case ASTView: return new ASTViewAction();
- case DumpRawTokens: return new DumpRawTokensAction();
- case DumpTokens: return new DumpTokensAction();
- case EmitAssembly: return new EmitAssemblyAction();
- case EmitBC: return new EmitBCAction();
- case EmitHTML: return new HTMLPrintAction();
- case EmitLLVM: return new EmitLLVMAction();
- case EmitLLVMOnly: return new EmitLLVMOnlyAction();
- case EmitCodeGenOnly: return new EmitCodeGenOnlyAction();
- case EmitObj: return new EmitObjAction();
- case FixIt: return new FixItAction();
- case GeneratePCH: return new GeneratePCHAction();
- case GeneratePTH: return new GeneratePTHAction();
- case InitOnly: return new InitOnlyAction();
- case ParseSyntaxOnly: return new SyntaxOnlyAction();
-
- case PluginAction: {
- for (FrontendPluginRegistry::iterator it =
- FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
- it != ie; ++it) {
- if (it->getName() == CI.getFrontendOpts().ActionName) {
- llvm::OwningPtr<PluginASTAction> P(it->instantiate());
- if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs))
- return 0;
- return P.take();
- }
- }
-
- CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
- << CI.getFrontendOpts().ActionName;
- return 0;
- }
-
- case PrintDeclContext: return new DeclContextPrintAction();
- case PrintPreamble: return new PrintPreambleAction();
- case PrintPreprocessedInput: return new PrintPreprocessedAction();
- case RewriteMacros: return new RewriteMacrosAction();
- case RewriteObjC: return new RewriteObjCAction();
- case RewriteTest: return new RewriteTestAction();
- //case RunAnalysis: return new AnalysisAction();
- case RunPreprocessorOnly: return new PreprocessOnlyAction();
- }
-}
-
-static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
- // Create the underlying action.
- FrontendAction *Act = CreateFrontendBaseAction(CI);
- if (!Act)
- return 0;
-
- // If there are any AST files to merge, create a frontend action
- // adaptor to perform the merge.
- if (!CI.getFrontendOpts().ASTMergeFiles.empty())
- Act = new ASTMergeAction(Act, CI.getFrontendOpts().ASTMergeFiles);
-
- return Act;
+ return P.str();
}
//===----------------------------------------------------------------------===//
@@ -178,30 +97,21 @@ static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
//===----------------------------------------------------------------------===//
ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
- ClangExpression &expr) :
+ ClangExpression &expr,
+ bool generate_debug_info) :
m_expr (expr),
m_compiler (),
m_code_generator ()
{
- // Initialize targets first, so that --version shows registered targets.
- static struct InitializeLLVM {
- InitializeLLVM() {
- llvm::InitializeAllTargets();
- llvm::InitializeAllAsmPrinters();
- llvm::InitializeAllTargetMCs();
- llvm::InitializeAllDisassemblers();
- }
- } InitializeLLVM;
-
// 1. Create a new compiler instance.
- m_compiler.reset(new CompilerInstance());
-
+ m_compiler.reset(new CompilerInstance());
+
// 2. Install the target.
lldb::TargetSP target_sp;
if (exe_scope)
target_sp = exe_scope->CalculateTarget();
-
+
// TODO: figure out what to really do when we don't have a valid target.
// Sometimes this will be ok to just use the host target triple (when we
// evaluate say "2+3", but other expressions like breakpoint conditions
@@ -210,48 +120,40 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
if (target_sp && target_sp->GetArchitecture().IsValid())
{
std::string triple = target_sp->GetArchitecture().GetTriple().str();
-
- int dash_count = 0;
- for (size_t i = 0; i < triple.size(); ++i)
- {
- if (triple[i] == '-')
- dash_count++;
- if (dash_count == 3)
- {
- triple.resize(i);
- break;
- }
- }
-
m_compiler->getTargetOpts().Triple = triple;
}
else
{
m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
}
-
+
if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 ||
target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
{
m_compiler->getTargetOpts().Features.push_back("+sse");
m_compiler->getTargetOpts().Features.push_back("+sse2");
}
-
- if (m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos)
+
+ // Any arm32 iOS environment, but not on arm64
+ if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos &&
+ m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos &&
+ m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos)
+ {
m_compiler->getTargetOpts().ABI = "apcs-gnu";
-
+ }
+
m_compiler->createDiagnostics();
-
+
// Create the target instance.
- m_compiler->setTarget(TargetInfo::CreateTargetInfo(m_compiler->getDiagnostics(),
- &m_compiler->getTargetOpts()));
-
+ m_compiler->setTarget(TargetInfo::CreateTargetInfo(
+ m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts));
+
assert (m_compiler->hasTarget());
-
+
// 3. Set options.
-
+
lldb::LanguageType language = expr.Language();
-
+
switch (language)
{
case lldb::eLanguageTypeC:
@@ -272,20 +174,20 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
m_compiler->getLangOpts().CPlusPlus11 = true;
break;
}
-
+
m_compiler->getLangOpts().Bool = true;
m_compiler->getLangOpts().WChar = true;
m_compiler->getLangOpts().Blocks = true;
m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients
if (expr.DesiredResultType() == ClangExpression::eResultTypeId)
m_compiler->getLangOpts().DebuggerCastResultToId = true;
-
+
// Spell checking is a nice feature, but it ends up completing a
// lot of types that we didn't strictly speaking need to complete.
// As a result, we spend a long time parsing and importing debug
// information.
- m_compiler->getLangOpts().SpellChecking = false;
-
+ m_compiler->getLangOpts().SpellChecking = false;
+
lldb::ProcessSP process_sp;
if (exe_scope)
process_sp = exe_scope->CalculateProcess();
@@ -298,7 +200,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
else
m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7));
-
+
if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing())
m_compiler->getLangOpts().DebuggerObjCLiteral = true;
}
@@ -307,62 +209,67 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
m_compiler->getLangOpts().ThreadsafeStatics = false;
m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access
m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
-
+
// Set CodeGen options
m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
m_compiler->getCodeGenOpts().InstrumentFunctions = false;
m_compiler->getCodeGenOpts().DisableFPElim = true;
m_compiler->getCodeGenOpts().OmitLeafFramePointer = false;
-
+ if (generate_debug_info)
+ m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::FullDebugInfo);
+ else
+ m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::NoDebugInfo);
+
// Disable some warnings.
- m_compiler->getDiagnostics().setDiagnosticGroupMapping("unused-value", clang::diag::MAP_IGNORE, SourceLocation());
- m_compiler->getDiagnostics().setDiagnosticGroupMapping("odr", clang::diag::MAP_IGNORE, SourceLocation());
-
+ m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError,
+ "unused-value", clang::diag::Severity::Ignored, SourceLocation());
+ m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError,
+ "odr", clang::diag::Severity::Ignored, SourceLocation());
+
// Inform the target of the language options
//
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
- m_compiler->getTarget().setForcedLangOptions(m_compiler->getLangOpts());
-
+ m_compiler->getTarget().adjust(m_compiler->getLangOpts());
+
// 4. Set up the diagnostic buffer for reporting errors
-
+
m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer);
-
+
// 5. Set up the source management objects inside the compiler
-
+
clang::FileSystemOptions file_system_options;
m_file_manager.reset(new clang::FileManager(file_system_options));
-
+
if (!m_compiler->hasSourceManager())
m_compiler->createSourceManager(*m_file_manager.get());
-
+
m_compiler->createFileManager();
- m_compiler->createPreprocessor();
-
- // 6. Most of this we get from the CompilerInstance, but we
+ m_compiler->createPreprocessor(TU_Complete);
+
+ // 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());
m_builtin_context.reset(new Builtin::Context());
-
+
std::unique_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(),
m_compiler->getSourceManager(),
- &m_compiler->getTarget(),
m_compiler->getPreprocessor().getIdentifierTable(),
*m_selector_table.get(),
- *m_builtin_context.get(),
- 0));
-
+ *m_builtin_context.get()));
+ ast_context->InitBuiltinTypes(m_compiler->getTarget());
+
ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
-
+
if (decl_map)
{
- llvm::OwningPtr<clang::ExternalASTSource> ast_source(decl_map->CreateProxy());
+ llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source(decl_map->CreateProxy());
decl_map->InstallASTContext(ast_context.get());
ast_context->setExternalSource(ast_source);
}
-
+
m_compiler->setASTContext(ast_context.release());
-
+
std::string module_name("$__lldb_module");
m_llvm_context.reset(new LLVMContext());
@@ -381,34 +288,77 @@ unsigned
ClangExpressionParser::Parse (Stream &stream)
{
TextDiagnosticBuffer *diag_buf = static_cast<TextDiagnosticBuffer*>(m_compiler->getDiagnostics().getClient());
-
+
diag_buf->FlushDiagnostics (m_compiler->getDiagnostics());
-
- MemoryBuffer *memory_buffer = MemoryBuffer::getMemBufferCopy(m_expr.Text(), __FUNCTION__);
- m_compiler->getSourceManager().createMainFileIDForMemBuffer (memory_buffer);
-
+
+ const char *expr_text = m_expr.Text();
+
+ clang::SourceManager &SourceMgr = m_compiler->getSourceManager();
+ bool created_main_file = false;
+ if (m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo)
+ {
+ std::string temp_source_path;
+
+ FileSpec tmpdir_file_spec;
+ if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
+ {
+ tmpdir_file_spec.AppendPathComponent("expr.XXXXXX");
+ temp_source_path = std::move(tmpdir_file_spec.GetPath());
+ }
+ else
+ {
+ temp_source_path = "/tmp/expr.XXXXXX";
+ }
+
+ if (mktemp(&temp_source_path[0]))
+ {
+ lldb_private::File file (temp_source_path.c_str(),
+ File::eOpenOptionWrite | File::eOpenOptionCanCreateNewOnly,
+ lldb::eFilePermissionsFileDefault);
+ const size_t expr_text_len = strlen(expr_text);
+ size_t bytes_written = expr_text_len;
+ if (file.Write(expr_text, bytes_written).Success())
+ {
+ if (bytes_written == expr_text_len)
+ {
+ file.Close();
+ SourceMgr.setMainFileID(SourceMgr.createFileID(
+ m_file_manager->getFile(temp_source_path),
+ SourceLocation(), SrcMgr::C_User));
+ created_main_file = true;
+ }
+ }
+ }
+ }
+
+ if (!created_main_file)
+ {
+ std::unique_ptr<MemoryBuffer> memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__);
+ SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(memory_buffer)));
+ }
+
diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor());
-
+
ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get());
-
+
if (ast_transformer)
ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext());
- else
- ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext());
-
+ else
+ ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext());
+
diag_buf->EndSourceFile();
-
+
TextDiagnosticBuffer::const_iterator diag_iterator;
-
+
int num_errors = 0;
-
+
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)
@@ -416,12 +366,12 @@ ClangExpressionParser::Parse (Stream &stream)
num_errors++;
stream.Printf("error: %s\n", (*diag_iterator).second.c_str());
}
-
+
for (diag_iterator = diag_buf->note_begin();
diag_iterator != diag_buf->note_end();
++diag_iterator)
stream.Printf("note: %s\n", (*diag_iterator).second.c_str());
-
+
if (!num_errors)
{
if (m_expr.DeclMap() && !m_expr.DeclMap()->ResolveUnknownTypes())
@@ -430,7 +380,7 @@ ClangExpressionParser::Parse (Stream &stream)
num_errors++;
}
}
-
+
return num_errors;
}
@@ -441,21 +391,21 @@ static bool FindFunctionInModule (ConstString &mangled_name,
for (llvm::Module::iterator fi = module->getFunctionList().begin(), fe = module->getFunctionList().end();
fi != fe;
++fi)
- {
+ {
if (fi->getName().str().find(orig_name) != std::string::npos)
{
mangled_name.SetCString(fi->getName().str().c_str());
return true;
}
}
-
+
return false;
}
Error
-ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
+ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
lldb::addr_t &func_end,
- std::unique_ptr<IRExecutionUnit> &execution_unit_ap,
+ std::shared_ptr<IRExecutionUnit> &execution_unit_sp,
ExecutionContext &exe_ctx,
bool &can_interpret,
ExecutionPolicy execution_policy)
@@ -464,24 +414,22 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
func_end = LLDB_INVALID_ADDRESS;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- std::unique_ptr<llvm::ExecutionEngine> execution_engine_ap;
-
Error err;
-
- std::unique_ptr<llvm::Module> module_ap (m_code_generator->ReleaseModule());
- if (!module_ap.get())
+ std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule());
+
+ if (!llvm_module_ap.get())
{
err.SetErrorToGenericError();
err.SetErrorString("IR doesn't contain a module");
return err;
}
-
+
// Find the actual name of the function (it's often mangled somehow)
-
+
ConstString function_name;
-
- if (!FindFunctionInModule(function_name, module_ap.get(), m_expr.FunctionName()))
+
+ if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName()))
{
err.SetErrorToGenericError();
err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
@@ -492,54 +440,54 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
if (log)
log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName());
}
-
- m_execution_unit.reset(new IRExecutionUnit(m_llvm_context, // handed off here
- module_ap, // handed off here
- function_name,
- exe_ctx.GetTargetSP(),
- m_compiler->getTargetOpts().Features));
-
+
+ execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here
+ llvm_module_ap, // handed off here
+ function_name,
+ exe_ctx.GetTargetSP(),
+ m_compiler->getTargetOpts().Features));
+
ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
-
+
if (decl_map)
{
Stream *error_stream = NULL;
Target *target = exe_ctx.GetTargetPtr();
if (target)
error_stream = target->GetDebugger().GetErrorFile().get();
-
+
IRForTarget ir_for_target(decl_map,
m_expr.NeedsVariableResolution(),
- *m_execution_unit,
+ *execution_unit_sp,
error_stream,
function_name.AsCString());
-
- bool ir_can_run = ir_for_target.runOnModule(*m_execution_unit->GetModule());
-
+
+ bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());
+
Error interpret_error;
-
- can_interpret = IRInterpreter::CanInterpret(*m_execution_unit->GetModule(), *m_execution_unit->GetFunction(), interpret_error);
-
+
+ can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error);
+
Process *process = exe_ctx.GetProcessPtr();
-
+
if (!ir_can_run)
{
err.SetErrorString("The expression could not be prepared to run in the target");
return err;
}
-
+
if (!can_interpret && execution_policy == eExecutionPolicyNever)
{
err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString());
return err;
}
-
+
if (!process && execution_policy == eExecutionPolicyAlways)
{
err.SetErrorString("Expression needed to run in the target, but the target can't be run");
return err;
}
-
+
if (execution_policy == eExecutionPolicyAlways || !can_interpret)
{
if (m_expr.NeedsValidation() && process)
@@ -547,44 +495,50 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
if (!process->GetDynamicCheckers())
{
DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
-
+
StreamString install_errors;
-
+
if (!dynamic_checkers->Install(install_errors, exe_ctx))
{
if (install_errors.GetString().empty())
err.SetErrorString ("couldn't install checkers, unknown error");
else
err.SetErrorString (install_errors.GetString().c_str());
-
+
return err;
}
-
+
process->SetDynamicCheckers(dynamic_checkers);
-
+
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
}
-
+
IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString());
-
- if (!ir_dynamic_checks.runOnModule(*m_execution_unit->GetModule()))
+
+ if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule()))
{
err.SetErrorToGenericError();
err.SetErrorString("Couldn't add dynamic checks to the expression");
return err;
}
}
-
- m_execution_unit->GetRunnableInfo(err, func_addr, func_end);
+
+ execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
}
}
else
{
- m_execution_unit->GetRunnableInfo(err, func_addr, func_end);
+ execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
}
-
- execution_unit_ap.reset (m_execution_unit.release());
-
+
return err;
}
+
+bool
+ClangExpressionParser::GetGenerateDebugInfo () const
+{
+ if (m_compiler)
+ return m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo;
+ return false;
+}
diff --git a/source/Expression/ClangExpressionVariable.cpp b/source/Expression/ClangExpressionVariable.cpp
index 0d355ce341c9..c3eae41473e9 100644
--- a/source/Expression/ClangExpressionVariable.cpp
+++ b/source/Expression/ClangExpressionVariable.cpp
@@ -8,11 +8,6 @@
//===----------------------------------------------------------------------===//
#include "lldb/Expression/ClangExpressionVariable.h"
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "clang/AST/ASTContext.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/DataExtractor.h"
@@ -44,17 +39,17 @@ ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &val
//----------------------------------------------------------------------
/// Return the variable's size in bytes
//----------------------------------------------------------------------
-size_t
+size_t
ClangExpressionVariable::GetByteSize ()
{
return m_frozen_sp->GetByteSize();
-}
+}
const ConstString &
ClangExpressionVariable::GetName ()
{
return m_frozen_sp->GetName();
-}
+}
lldb::ValueObjectSP
ClangExpressionVariable::GetValueObject()
@@ -78,13 +73,13 @@ ClangASTType
ClangExpressionVariable::GetClangType()
{
return m_frozen_sp->GetClangType();
-}
+}
void
ClangExpressionVariable::SetClangType(const ClangASTType &clang_type)
{
m_frozen_sp->GetValue().SetClangType(clang_type);
-}
+}
TypeFromUser
@@ -92,7 +87,7 @@ ClangExpressionVariable::GetTypeFromUser()
{
TypeFromUser tfu (m_frozen_sp->GetClangType());
return tfu;
-}
+}
uint8_t *
ClangExpressionVariable::GetValueBytes()
@@ -130,7 +125,7 @@ ClangExpressionVariable::TransferAddress (bool force)
if (m_frozen_sp.get() == NULL)
return;
-
+
if (force || (m_frozen_sp->GetLiveAddress() == LLDB_INVALID_ADDRESS))
m_frozen_sp->SetLiveAddress(m_live_sp->GetLiveAddress());
}
diff --git a/source/Expression/ClangFunction.cpp b/source/Expression/ClangFunction.cpp
index e707c60ffced..27afba2898ab 100644
--- a/source/Expression/ClangFunction.cpp
+++ b/source/Expression/ClangFunction.cpp
@@ -22,18 +22,20 @@
#include "llvm/IR/Module.h"
// Project includes
-#include "lldb/Expression/ASTStructExtractor.h"
-#include "lldb/Expression/ClangExpressionParser.h"
-#include "lldb/Expression/ClangFunction.h"
-#include "lldb/Expression/IRExecutionUnit.h"
-#include "lldb/Symbol/Type.h"
#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/State.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Expression/ASTStructExtractor.h"
+#include "lldb/Expression/ClangExpressionParser.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Type.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -41,7 +43,6 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
-#include "lldb/Core/Log.h"
using namespace lldb_private;
@@ -53,8 +54,13 @@ ClangFunction::ClangFunction
ExecutionContextScope &exe_scope,
const ClangASTType &return_type,
const Address& functionAddress,
- const ValueList &arg_value_list
+ const ValueList &arg_value_list,
+ const char *name
) :
+ m_parser(),
+ m_execution_unit_sp(),
+ m_jit_module_wp(),
+ m_name (name ? name : "<unknown>"),
m_function_ptr (NULL),
m_function_addr (functionAddress),
m_function_return_type(return_type),
@@ -75,8 +81,10 @@ ClangFunction::ClangFunction
ExecutionContextScope &exe_scope,
Function &function,
ClangASTContext *ast_context,
- const ValueList &arg_value_list
+ const ValueList &arg_value_list,
+ const char *name
) :
+ m_name (name ? name : "<unknown>"),
m_function_ptr (&function),
m_function_addr (),
m_function_return_type (),
@@ -87,7 +95,7 @@ ClangFunction::ClangFunction
m_compiled (false),
m_JITted (false)
{
- m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
+ m_jit_process_wp = exe_scope.CalculateProcess();
// Can't make a ClangFunction without a process.
assert (m_jit_process_wp.lock());
@@ -100,6 +108,13 @@ ClangFunction::ClangFunction
//----------------------------------------------------------------------
ClangFunction::~ClangFunction()
{
+ lldb::ProcessSP process_sp (m_jit_process_wp.lock());
+ if (process_sp)
+ {
+ lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
+ if (jit_module_sp)
+ process_sp->GetTarget().GetImages().Remove(jit_module_sp);
+ }
}
unsigned
@@ -173,7 +188,7 @@ ClangFunction::CompileFunction (Stream &errors)
}
else
{
- errors.Printf("Could not determine type of input value %zu.", i);
+ errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i);
return 1;
}
}
@@ -222,7 +237,8 @@ ClangFunction::CompileFunction (Stream &errors)
lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
if (jit_process_sp)
{
- m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this));
+ const bool generate_debug_info = true;
+ m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info));
num_errors = m_parser->Parse (errors);
}
@@ -263,7 +279,7 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr,
m_jit_end_addr,
- m_execution_unit_ap,
+ m_execution_unit_sp,
exe_ctx,
can_interpret,
eExecutionPolicyAlways));
@@ -271,8 +287,22 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
if (!jit_error.Success())
return false;
+ if (m_parser->GetGenerateDebugInfo())
+ {
+ lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
+
+ if (jit_module_sp)
+ {
+ ConstString const_func_name(FunctionName());
+ FileSpec jit_file;
+ jit_file.GetFilename() = const_func_name;
+ jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
+ m_jit_module_wp = jit_module_sp;
+ process->GetTarget().GetImages().Append(jit_module_sp);
+ }
+ }
if (process && m_jit_start_addr)
- m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
+ m_jit_process_wp = process->shared_from_this();
m_JITted = true;
@@ -304,7 +334,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
Error error;
using namespace clang;
- ExecutionResults return_value = eExecutionSetupError;
+ lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
Process *process = exe_ctx.GetProcessPtr();
@@ -344,7 +374,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
size_t num_args = arg_values.GetSize();
if (num_args != m_arg_values.GetSize())
{
- errors.Printf ("Wrong number of arguments - was: %zu should be: %zu", num_args, m_arg_values.GetSize());
+ errors.Printf ("Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", (uint64_t)num_args, (uint64_t)m_arg_values.GetSize());
return false;
}
@@ -401,7 +431,7 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
- log->Printf("-- [ClangFunction::GetThreadPlanToCallFunction] Creating thread plan to call function --");
+ log->Printf("-- [ClangFunction::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str());
// FIXME: Use the errors Stream for better error reporting.
Thread *thread = exe_ctx.GetThreadPtr();
@@ -438,7 +468,7 @@ ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t arg
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
- log->Printf("-- [ClangFunction::FetchFunctionResults] Fetching function results --");
+ log->Printf("-- [ClangFunction::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str());
Process *process = exe_ctx.GetProcessPtr();
@@ -472,7 +502,7 @@ ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_
exe_ctx.GetProcessRef().DeallocateMemory(args_addr);
}
-ExecutionResults
+lldb::ExpressionResults
ClangFunction::ExecuteFunction(
ExecutionContext &exe_ctx,
lldb::addr_t *args_addr_ptr,
@@ -481,7 +511,7 @@ ClangFunction::ExecuteFunction(
Value &results)
{
using namespace clang;
- ExecutionResults return_value = eExecutionSetupError;
+ lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
// ClangFunction::ExecuteFunction execution is always just to get the result. Do make sure we ignore
// breakpoints, unwind on error, and don't try to debug it.
@@ -498,27 +528,27 @@ ClangFunction::ExecuteFunction(
args_addr = LLDB_INVALID_ADDRESS;
if (CompileFunction(errors) != 0)
- return eExecutionSetupError;
+ return lldb::eExpressionSetupError;
if (args_addr == LLDB_INVALID_ADDRESS)
{
if (!InsertFunction(exe_ctx, args_addr, errors))
- return eExecutionSetupError;
+ return lldb::eExpressionSetupError;
}
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
- log->Printf("== [ClangFunction::ExecuteFunction] Executing function ==");
+ log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str());
lldb::ThreadPlanSP call_plan_sp (GetThreadPlanToCallFunction (exe_ctx,
args_addr,
real_options,
errors));
if (!call_plan_sp)
- return eExecutionSetupError;
+ return lldb::eExpressionSetupError;
- // <rdar://problem/12027563> we need to make sure we record the fact that we are running an expression here
+ // We need to make sure we record the fact that we are running an expression here
// otherwise this fact will fail to be recorded when fetching an Objective-C object description
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
@@ -530,13 +560,13 @@ ClangFunction::ExecuteFunction(
if (log)
{
- if (return_value != eExecutionCompleted)
+ if (return_value != lldb::eExpressionCompleted)
{
- log->Printf("== [ClangFunction::ExecuteFunction] Execution completed abnormally ==");
+ log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str());
}
else
{
- log->Printf("== [ClangFunction::ExecuteFunction] Execution completed normally ==");
+ log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str());
}
}
@@ -546,7 +576,7 @@ ClangFunction::ExecuteFunction(
if (args_addr_ptr != NULL)
*args_addr_ptr = args_addr;
- if (return_value != eExecutionCompleted)
+ if (return_value != lldb::eExpressionCompleted)
return return_value;
FetchFunctionResults(exe_ctx, args_addr, results);
@@ -554,7 +584,7 @@ ClangFunction::ExecuteFunction(
if (args_addr_ptr == NULL)
DeallocateFunctionResults(exe_ctx, args_addr);
- return eExecutionCompleted;
+ return lldb::eExpressionCompleted;
}
clang::ASTConsumer *
diff --git a/source/Expression/ClangUserExpression.cpp b/source/Expression/ClangUserExpression.cpp
index 6b0eee8cf363..52ef4d310352 100644
--- a/source/Expression/ClangUserExpression.cpp
+++ b/source/Expression/ClangUserExpression.cpp
@@ -7,19 +7,18 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-// C++ Includes
#include <cstdlib>
#include <string>
#include <map>
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObjectConstResult.h"
@@ -32,10 +31,12 @@
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Expression/Materializer.h"
-#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/VariableList.h"
@@ -63,6 +64,11 @@ ClangUserExpression::ClangUserExpression (const char *expr,
m_language (language),
m_transformed_text (),
m_desired_type (desired_type),
+ m_expr_decl_map(),
+ m_execution_unit_sp(),
+ m_materializer_ap(),
+ m_result_synthesizer(),
+ m_jit_module_wp(),
m_enforce_valid_object (true),
m_cplusplus (false),
m_objectivec (false),
@@ -91,6 +97,12 @@ ClangUserExpression::ClangUserExpression (const char *expr,
ClangUserExpression::~ClangUserExpression ()
{
+ if (m_target)
+ {
+ lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
+ if (jit_module_sp)
+ m_target->GetImages().Remove(jit_module_sp);
+ }
}
clang::ASTConsumer *
@@ -98,7 +110,7 @@ ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
{
m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough,
*m_target));
-
+
return m_result_synthesizer.get();
}
@@ -109,16 +121,16 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
if (log)
log->Printf("ClangUserExpression::ScanContext()");
-
+
m_target = exe_ctx.GetTargetPtr();
-
+
if (!(m_allow_cxx || m_allow_objc))
{
if (log)
log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C");
return;
}
-
+
StackFrame *frame = exe_ctx.GetFramePtr();
if (frame == NULL)
{
@@ -126,19 +138,19 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
log->Printf(" [CUE::SC] Null stack frame");
return;
}
-
+
SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
-
+
if (!sym_ctx.function)
{
if (log)
log->Printf(" [CUE::SC] Null function");
return;
}
-
+
// Find the block that defines the function represented by "sym_ctx"
Block *function_block = sym_ctx.GetFunctionBlock();
-
+
if (!function_block)
{
if (log)
@@ -154,7 +166,7 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
log->Printf(" [CUE::SC] Null decl context");
return;
}
-
+
if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context))
{
if (m_allow_cxx && method_decl->isInstance())
@@ -162,60 +174,60 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
if (m_enforce_valid_object)
{
lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
-
+
const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context";
-
+
if (!variable_list_sp)
{
err.SetErrorString(thisErrorString);
return;
}
-
+
lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
-
+
if (!this_var_sp ||
- !this_var_sp->IsInScope(frame) ||
+ !this_var_sp->IsInScope(frame) ||
!this_var_sp->LocationIsValidForFrame (frame))
{
err.SetErrorString(thisErrorString);
return;
}
}
-
+
m_cplusplus = true;
m_needs_object_ptr = true;
}
}
else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context))
- {
+ {
if (m_allow_objc)
{
if (m_enforce_valid_object)
{
lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
-
+
const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context";
-
+
if (!variable_list_sp)
{
err.SetErrorString(selfErrorString);
return;
}
-
+
lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
-
- if (!self_variable_sp ||
- !self_variable_sp->IsInScope(frame) ||
+
+ if (!self_variable_sp ||
+ !self_variable_sp->IsInScope(frame) ||
!self_variable_sp->LocationIsValidForFrame (frame))
{
err.SetErrorString(selfErrorString);
return;
}
}
-
+
m_objectivec = true;
m_needs_object_ptr = true;
-
+
if (!method_decl->isInstanceMethod())
m_static_method = true;
}
@@ -226,7 +238,7 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
// object pointer. The best way to deal with getting to the ivars at present it by pretending
// that this is a method of a class in whatever runtime the debug info says the object pointer
// belongs to. Do that here.
-
+
ClangASTMetadata *metadata = ClangASTContext::GetMetadata (&decl_context->getParentASTContext(), function_decl);
if (metadata && metadata->HasObjectPtr())
{
@@ -236,17 +248,17 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
if (m_enforce_valid_object)
{
lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
-
+
const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context";
-
+
if (!variable_list_sp)
{
err.SetErrorString(thisErrorString);
return;
}
-
+
lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
-
+
if (!this_var_sp ||
!this_var_sp->IsInScope(frame) ||
!this_var_sp->LocationIsValidForFrame (frame))
@@ -255,7 +267,7 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
return;
}
}
-
+
m_cplusplus = true;
m_needs_object_ptr = true;
}
@@ -264,17 +276,17 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
if (m_enforce_valid_object)
{
lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
-
+
const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context";
-
+
if (!variable_list_sp)
{
err.SetErrorString(selfErrorString);
return;
}
-
+
lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
-
+
if (!self_variable_sp ||
!self_variable_sp->IsInScope(frame) ||
!self_variable_sp->LocationIsValidForFrame (frame))
@@ -282,23 +294,23 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
err.SetErrorString(selfErrorString);
return;
}
-
+
Type *self_type = self_variable_sp->GetType();
-
+
if (!self_type)
{
err.SetErrorString(selfErrorString);
return;
}
-
+
ClangASTType self_clang_type = self_type->GetClangForwardType();
-
+
if (!self_clang_type)
{
err.SetErrorString(selfErrorString);
return;
}
-
+
if (self_clang_type.IsObjCClassType())
{
return;
@@ -328,9 +340,9 @@ void
ClangUserExpression::InstallContext (ExecutionContext &exe_ctx)
{
m_process_wp = exe_ctx.GetProcessSP();
-
+
lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
-
+
if (frame_sp)
m_address = frame_sp->GetFrameCodeAddress();
}
@@ -346,11 +358,11 @@ ClangUserExpression::LockAndCheckContext (ExecutionContext &exe_ctx,
if (process_sp != expected_process_sp)
return false;
-
+
process_sp = exe_ctx.GetProcessSP();
target_sp = exe_ctx.GetTargetSP();
frame_sp = exe_ctx.GetFrameSP();
-
+
if (m_address.IsValid())
{
if (!frame_sp)
@@ -358,7 +370,7 @@ ClangUserExpression::LockAndCheckContext (ExecutionContext &exe_ctx,
else
return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get()));
}
-
+
return true;
}
@@ -368,7 +380,7 @@ ClangUserExpression::MatchesContext (ExecutionContext &exe_ctx)
lldb::TargetSP target_sp;
lldb::ProcessSP process_sp;
lldb::StackFrameSP frame_sp;
-
+
return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
}
@@ -383,7 +395,7 @@ ApplyObjcCastHack(std::string &expr)
#define OBJC_CAST_HACK_TO "(int)(long long)["
size_t from_offset;
-
+
while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
@@ -396,99 +408,100 @@ ApplyObjcCastHack(std::string &expr)
// hopefully we'll figure out a way to #include the same environment as is
// present in the original source file rather than try to hack specific type
// definitions in as needed.
-static void
-ApplyUnicharHack(std::string &expr)
-{
-#define UNICHAR_HACK_FROM "unichar"
-#define UNICHAR_HACK_TO "unsigned short"
-
- size_t from_offset;
-
- while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
- expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
-
-#undef UNICHAR_HACK_TO
-#undef UNICHAR_HACK_FROM
-}
+//static void
+//ApplyUnicharHack(std::string &expr)
+//{
+//#define UNICHAR_HACK_FROM "unichar"
+//#define UNICHAR_HACK_TO "unsigned short"
+//
+// size_t from_offset;
+//
+// while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
+// expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
+//
+//#undef UNICHAR_HACK_TO
+//#undef UNICHAR_HACK_FROM
+//}
bool
-ClangUserExpression::Parse (Stream &error_stream,
+ClangUserExpression::Parse (Stream &error_stream,
ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy,
- bool keep_result_in_memory)
+ bool keep_result_in_memory,
+ bool generate_debug_info)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
Error err;
-
+
InstallContext(exe_ctx);
-
+
ScanContext(exe_ctx, err);
-
+
if (!err.Success())
{
error_stream.Printf("warning: %s\n", err.AsCString());
}
-
+
StreamString m_transformed_stream;
-
+
////////////////////////////////////
// Generate the expression
//
-
+
ApplyObjcCastHack(m_expr_text);
//ApplyUnicharHack(m_expr_text);
std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(m_expr_prefix.c_str(), m_expr_text.c_str()));
-
+
lldb::LanguageType lang_type;
-
+
if (m_cplusplus)
lang_type = lldb::eLanguageTypeC_plus_plus;
else if(m_objectivec)
lang_type = lldb::eLanguageTypeObjC;
else
lang_type = lldb::eLanguageTypeC;
-
- if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method))
+
+ if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method, exe_ctx))
{
error_stream.PutCString ("error: couldn't construct expression body");
return false;
}
-
+
if (log)
log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
-
+
////////////////////////////////////
// Set up the target and compiler
//
-
+
Target *target = exe_ctx.GetTargetPtr();
-
+
if (!target)
{
error_stream.PutCString ("error: invalid target\n");
return false;
}
-
+
//////////////////////////
// Parse the expression
//
-
+
m_materializer_ap.reset(new Materializer());
-
+
m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
-
+
class OnExit
{
public:
typedef std::function <void (void)> Callback;
-
+
OnExit (Callback const &callback) :
m_callback(callback)
{
}
-
+
~OnExit ()
{
m_callback();
@@ -496,50 +509,81 @@ ClangUserExpression::Parse (Stream &error_stream,
private:
Callback m_callback;
};
-
+
OnExit on_exit([this]() { m_expr_decl_map.reset(); });
-
+
if (!m_expr_decl_map->WillParse(exe_ctx, m_materializer_ap.get()))
{
error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
-
+
m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.
-
+
return false;
}
-
+
Process *process = exe_ctx.GetProcessPtr();
ExecutionContextScope *exe_scope = process;
-
+
if (!exe_scope)
exe_scope = exe_ctx.GetTargetPtr();
-
- ClangExpressionParser parser(exe_scope, *this);
-
+
+ ClangExpressionParser parser(exe_scope, *this, generate_debug_info);
+
unsigned num_errors = parser.Parse (error_stream);
-
+
if (num_errors)
{
error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
-
+
m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.
-
+
return false;
}
-
+
//////////////////////////////////////////////////////////////////////////////////////////
// Prepare the output of the parser for execution, evaluating it statically if possible
//
-
+
Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
m_jit_end_addr,
- m_execution_unit_ap,
+ m_execution_unit_sp,
exe_ctx,
m_can_interpret,
execution_policy);
-
+
+ if (generate_debug_info)
+ {
+ lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
+
+ if (jit_module_sp)
+ {
+ ConstString const_func_name(FunctionName());
+ FileSpec jit_file;
+ jit_file.GetFilename() = const_func_name;
+ jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
+ m_jit_module_wp = jit_module_sp;
+ target->GetImages().Append(jit_module_sp);
+ }
+// lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile();
+// StreamFile strm (stdout, false);
+// if (jit_obj_file)
+// {
+// jit_obj_file->GetSectionList();
+// jit_obj_file->GetSymtab();
+// jit_obj_file->Dump(&strm);
+// }
+// lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor();
+// if (jit_sym_vendor)
+// {
+// lldb_private::SymbolContextList sc_list;
+// jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list);
+// sc_list.Dump(&strm, target);
+// jit_sym_vendor->Dump(&strm);
+// }
+ }
+
m_expr_decl_map.reset(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions.
-
+
if (jit_error.Success())
{
if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
@@ -563,16 +607,16 @@ GetObjectPointer (lldb::StackFrameSP frame_sp,
Error &err)
{
err.Clear();
-
+
if (!frame_sp)
{
err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString());
return LLDB_INVALID_ADDRESS;
}
-
+
lldb::VariableSP var_sp;
lldb::ValueObjectSP valobj_sp;
-
+
valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(),
lldb::eNoDynamicValues,
StackFrame::eExpressionPathOptionCheckPtrVsMember ||
@@ -582,18 +626,18 @@ GetObjectPointer (lldb::StackFrameSP frame_sp,
StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
var_sp,
err);
-
+
if (!err.Success())
return LLDB_INVALID_ADDRESS;
-
+
lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
-
+
if (ret == LLDB_INVALID_ADDRESS)
{
err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString());
return LLDB_INVALID_ADDRESS;
}
-
+
return ret;
}
@@ -607,22 +651,22 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
lldb::TargetSP target;
lldb::ProcessSP process;
lldb::StackFrameSP frame;
-
+
if (!LockAndCheckContext(exe_ctx,
target,
- process,
+ process,
frame))
{
error_stream.Printf("The context has changed before we could JIT the expression!\n");
return false;
}
-
+
if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
- {
+ {
if (m_needs_object_ptr)
{
ConstString object_name;
-
+
if (m_cplusplus)
{
object_name.SetCString("this");
@@ -636,23 +680,23 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
error_stream.Printf("Need object pointer but don't know the language\n");
return false;
}
-
+
Error object_ptr_error;
-
+
object_ptr = GetObjectPointer(frame, object_name, object_ptr_error);
-
+
if (!object_ptr_error.Success())
{
error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
object_ptr = 0;
}
-
+
if (m_objectivec)
{
ConstString cmd_name("_cmd");
-
+
cmd_ptr = GetObjectPointer(frame, cmd_name, object_ptr_error);
-
+
if (!object_ptr_error.Success())
{
error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
@@ -660,56 +704,56 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
}
}
}
-
+
if (m_materialized_address == LLDB_INVALID_ADDRESS)
{
Error alloc_error;
-
+
IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
-
- m_materialized_address = m_execution_unit_ap->Malloc(m_materializer_ap->GetStructByteSize(),
+
+ m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(),
m_materializer_ap->GetStructAlignment(),
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
policy,
alloc_error);
-
+
if (!alloc_error.Success())
{
error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
return false;
}
}
-
+
struct_address = m_materialized_address;
-
+
if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
{
Error alloc_error;
const size_t stack_frame_size = 512 * 1024;
-
- m_stack_frame_bottom = m_execution_unit_ap->Malloc(stack_frame_size,
+
+ m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size,
8,
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
IRMemoryMap::eAllocationPolicyHostOnly,
alloc_error);
-
+
m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
-
+
if (!alloc_error.Success())
{
error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString());
return false;
}
}
-
+
Error materialize_error;
-
- m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_ap, struct_address, materialize_error);
-
+
+ m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
+
if (!materialize_error.Success())
{
- error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
+ error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString());
return false;
}
}
@@ -724,18 +768,18 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
lldb::addr_t function_stack_top)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (log)
log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
-
+
if (!m_dematerializer_sp)
{
error_stream.Printf ("Couldn't apply expression side effects : no dematerializer is present");
return false;
}
-
+
Error dematerialize_error;
-
+
m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_bottom, function_stack_top);
if (!dematerialize_error.Success())
@@ -743,16 +787,16 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
error_stream.Printf ("Couldn't apply expression side effects : %s\n", dematerialize_error.AsCString("unknown error"));
return false;
}
-
+
if (result)
result->TransferAddress();
-
+
m_dematerializer_sp.reset();
-
+
return true;
-}
+}
-ExecutionResults
+lldb::ExpressionResults
ClangUserExpression::Execute (Stream &error_stream,
ExecutionContext &exe_ctx,
const EvaluateExpressionOptions& options,
@@ -766,110 +810,118 @@ ClangUserExpression::Execute (Stream &error_stream,
if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
{
lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
-
+
lldb::addr_t object_ptr = 0;
lldb::addr_t cmd_ptr = 0;
-
+
if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
{
error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
- return eExecutionSetupError;
+ return lldb::eExpressionSetupError;
}
-
+
lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
-
+
if (m_can_interpret)
- {
- llvm::Module *module = m_execution_unit_ap->GetModule();
- llvm::Function *function = m_execution_unit_ap->GetFunction();
-
+ {
+ llvm::Module *module = m_execution_unit_sp->GetModule();
+ llvm::Function *function = m_execution_unit_sp->GetFunction();
+
if (!module || !function)
{
error_stream.Printf("Supposed to interpret, but nothing is there");
- return eExecutionSetupError;
+ return lldb::eExpressionSetupError;
}
Error interpreter_error;
-
+
llvm::SmallVector <lldb::addr_t, 3> args;
-
+
if (m_needs_object_ptr)
{
args.push_back(object_ptr);
-
+
if (m_objectivec)
args.push_back(cmd_ptr);
}
-
+
args.push_back(struct_address);
-
+
function_stack_bottom = m_stack_frame_bottom;
function_stack_top = m_stack_frame_top;
-
+
IRInterpreter::Interpret (*module,
*function,
args,
- *m_execution_unit_ap.get(),
+ *m_execution_unit_sp.get(),
interpreter_error,
function_stack_bottom,
function_stack_top);
-
+
if (!interpreter_error.Success())
{
error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
- return eExecutionDiscarded;
+ return lldb::eExpressionDiscarded;
}
}
else
{
+ if (!exe_ctx.HasThreadScope())
+ {
+ error_stream.Printf("ClangUserExpression::Execute called with no thread selected.");
+ return lldb::eExpressionSetupError;
+ }
+
Address wrapper_address (m_jit_start_addr);
-
+
llvm::SmallVector <lldb::addr_t, 3> args;
-
+
if (m_needs_object_ptr) {
args.push_back(object_ptr);
if (m_objectivec)
args.push_back(cmd_ptr);
}
-
+
args.push_back(struct_address);
-
- lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
- wrapper_address,
- args,
- options,
- shared_ptr_to_me));
-
+
+ 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);
+
if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
- return eExecutionSetupError;
-
- lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();
+ return lldb::eExpressionSetupError;
- function_stack_bottom = function_stack_pointer - Host::GetPageSize();
+ lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
+
+ function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
function_stack_top = function_stack_pointer;
-
+
if (log)
log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
-
+
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
-
- ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
+
+ lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
call_plan_sp,
options,
error_stream);
-
+
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
-
+
if (log)
log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
- if (execution_result == eExecutionInterrupted || execution_result == eExecutionHitBreakpoint)
+ if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
{
const char *error_desc = NULL;
-
+
if (call_plan_sp)
{
lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
@@ -880,45 +932,51 @@ ClangUserExpression::Execute (Stream &error_stream,
error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
else
error_stream.PutCString ("Execution was interrupted.");
-
- if ((execution_result == eExecutionInterrupted && options.DoesUnwindOnError())
- || (execution_result == eExecutionHitBreakpoint && options.DoesIgnoreBreakpoints()))
+
+ if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError())
+ || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation.");
else
- error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation.");
+ {
+ if (execution_result == lldb::eExpressionHitBreakpoint)
+ user_expression_plan->TransferExpressionOwnership();
+ error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, "
+ "use \"thread return -x\" to return to the state before expression evaluation.");
+ }
return execution_result;
}
- else if (execution_result == eExecutionStoppedForDebug)
+ else if (execution_result == lldb::eExpressionStoppedForDebug)
{
- error_stream.PutCString ("Execution was halted at the first instruction of the expression function because \"debug\" was requested.\n"
+ error_stream.PutCString ("Execution was halted at the first instruction of the expression "
+ "function because \"debug\" was requested.\n"
"Use \"thread return -x\" to return to the state before expression evaluation.");
return execution_result;
}
- else if (execution_result != eExecutionCompleted)
+ else if (execution_result != lldb::eExpressionCompleted)
{
error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
return execution_result;
}
}
-
+
if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
{
- return eExecutionCompleted;
+ return lldb::eExpressionCompleted;
}
else
{
- return eExecutionSetupError;
+ return lldb::eExpressionResultUnavailable;
}
}
else
{
error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
- return eExecutionSetupError;
+ return lldb::eExpressionSetupError;
}
}
-ExecutionResults
+lldb::ExpressionResults
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
const EvaluateExpressionOptions& options,
const char *expr_cstr,
@@ -931,8 +989,8 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
const lldb::LanguageType language = options.GetLanguage();
const ResultType desired_type = options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny;
- ExecutionResults execution_results = eExecutionSetupError;
-
+ lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
+
Process *process = exe_ctx.GetProcessPtr();
if (process == NULL || process->GetState() != lldb::eStateStopped)
@@ -941,31 +999,43 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
-
+
error.SetErrorString ("expression needed to run but couldn't");
-
+
return execution_results;
}
}
-
+
if (process == NULL || !process->CanJIT())
execution_policy = eExecutionPolicyNever;
-
+
ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix, language, desired_type));
StreamString error_stream;
-
+
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
-
+
const bool keep_expression_in_memory = true;
-
- if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory))
+ const bool generate_debug_info = options.GetGenerateDebugInfo();
+
+ if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
+ {
+ error.SetErrorString ("expression interrupted by callback before parse");
+ result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
+ return lldb::eExpressionInterrupted;
+ }
+
+ if (!user_expression_sp->Parse (error_stream,
+ exe_ctx,
+ execution_policy,
+ keep_expression_in_memory,
+ generate_debug_info))
{
if (error_stream.GetString().empty())
- error.SetErrorString ("expression failed to parse, unknown error");
+ error.SetExpressionError (lldb::eExpressionParseError, "expression failed to parse, unknown error");
else
- error.SetErrorString (error_stream.GetString().c_str());
+ error.SetExpressionError (lldb::eExpressionParseError, error_stream.GetString().c_str());
}
else
{
@@ -976,53 +1046,72 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
-
+
if (error_stream.GetString().empty())
- error.SetErrorString ("expression needed to run but couldn't");
+ error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
}
else
- {
+ {
+ if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
+ {
+ error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
+ result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
+ return lldb::eExpressionInterrupted;
+ }
+
error_stream.GetString().clear();
-
+
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
- execution_results = user_expression_sp->Execute (error_stream,
+ execution_results = user_expression_sp->Execute (error_stream,
exe_ctx,
options,
user_expression_sp,
expr_result);
-
- if (execution_results != eExecutionCompleted)
+
+ if (options.GetResultIsInternal())
+ {
+ process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result);
+ }
+
+ if (execution_results != lldb::eExpressionCompleted)
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
-
+
if (error_stream.GetString().empty())
- error.SetErrorString ("expression failed to execute, unknown error");
+ error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
else
- error.SetErrorString (error_stream.GetString().c_str());
+ error.SetExpressionError (execution_results, error_stream.GetString().c_str());
}
- else
+ else
{
if (expr_result)
{
result_valobj_sp = expr_result->GetValueObject();
-
+
if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString());
+ log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==",
+ result_valobj_sp->GetValueAsCString());
}
else
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
-
+
error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
}
}
}
}
-
+
+ if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
+ {
+ error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
+ return lldb::eExpressionInterrupted;
+ }
+
if (result_valobj_sp.get() == NULL)
{
result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
diff --git a/source/Expression/ClangUtilityFunction.cpp b/source/Expression/ClangUtilityFunction.cpp
index c911c279993f..de5b0c1b03f4 100644
--- a/source/Expression/ClangUtilityFunction.cpp
+++ b/source/Expression/ClangUtilityFunction.cpp
@@ -17,6 +17,7 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
@@ -42,6 +43,9 @@ using namespace lldb_private;
ClangUtilityFunction::ClangUtilityFunction (const char *text,
const char *name) :
ClangExpression (),
+ m_expr_decl_map (),
+ m_execution_unit_sp (),
+ m_jit_module_wp (),
m_function_text (ExpressionSourceCode::g_expression_prefix),
m_function_name (name)
{
@@ -51,6 +55,14 @@ ClangUtilityFunction::ClangUtilityFunction (const char *text,
ClangUtilityFunction::~ClangUtilityFunction ()
{
+ lldb::ProcessSP process_sp (m_jit_process_wp.lock());
+ if (process_sp)
+ {
+ lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
+ if (jit_module_sp)
+ process_sp->GetTarget().GetImages().Remove(jit_module_sp);
+ }
+
}
//------------------------------------------------------------------
@@ -108,8 +120,9 @@ ClangUtilityFunction::Install (Stream &error_stream,
error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
return false;
}
-
- ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this);
+
+ const bool generate_debug_info = true;
+ ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info);
unsigned num_errors = parser.Parse (error_stream);
@@ -130,13 +143,29 @@ ClangUtilityFunction::Install (Stream &error_stream,
Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
m_jit_end_addr,
- m_execution_unit_ap,
+ m_execution_unit_sp,
exe_ctx,
can_interpret,
eExecutionPolicyAlways);
if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
- m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
+ {
+ m_jit_process_wp = process->shared_from_this();
+ if (parser.GetGenerateDebugInfo())
+ {
+ lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
+
+ if (jit_module_sp)
+ {
+ ConstString const_func_name(FunctionName());
+ FileSpec jit_file;
+ jit_file.GetFilename() = const_func_name;
+ jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
+ m_jit_module_wp = jit_module_sp;
+ target->GetImages().Append(jit_module_sp);
+ }
+ }
+ }
#if 0
// jingham: look here
diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp
index 28aa6d02a56d..44b64ab1bf29 100644
--- a/source/Expression/DWARFExpression.cpp
+++ b/source/Expression/DWARFExpression.cpp
@@ -282,6 +282,33 @@ DWARFExpression::CopyOpcodeData (lldb::ModuleSP module_sp, const DataExtractor&
}
void
+DWARFExpression::CopyOpcodeData (const void *data,
+ lldb::offset_t data_length,
+ ByteOrder byte_order,
+ uint8_t addr_byte_size)
+{
+ if (data && data_length)
+ {
+ m_data.SetData(DataBufferSP(new DataBufferHeap(data, data_length)));
+ m_data.SetByteOrder(byte_order);
+ m_data.SetAddressByteSize(addr_byte_size);
+ }
+}
+
+void
+DWARFExpression::CopyOpcodeData (uint64_t const_value,
+ lldb::offset_t const_value_byte_size,
+ uint8_t addr_byte_size)
+{
+ if (const_value_byte_size)
+ {
+ m_data.SetData(DataBufferSP(new DataBufferHeap(&const_value, const_value_byte_size)));
+ m_data.SetByteOrder(endian::InlHostByteOrder());
+ m_data.SetAddressByteSize(addr_byte_size);
+ }
+}
+
+void
DWARFExpression::SetOpcodeData (lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length)
{
m_module_wp = module_sp;
@@ -728,7 +755,7 @@ static bool
ReadRegisterValueAsScalar
(
RegisterContext *reg_ctx,
- uint32_t reg_kind,
+ lldb::RegisterKind reg_kind,
uint32_t reg_num,
Error *error_ptr,
Value &value
@@ -1307,11 +1334,11 @@ DWARFExpression::Evaluate
ClangExpressionVariableList *expr_locals,
ClangExpressionDeclMap *decl_map,
RegisterContext *reg_ctx,
- lldb::ModuleSP opcode_ctx,
+ lldb::ModuleSP module_sp,
const DataExtractor& opcodes,
const lldb::offset_t opcodes_offset,
const lldb::offset_t opcodes_length,
- const uint32_t reg_kind,
+ const lldb::RegisterKind reg_kind,
const Value* initial_value_ptr,
Value& result,
Error *error_ptr
@@ -1345,6 +1372,10 @@ DWARFExpression::Evaluate
Value tmp;
uint32_t reg_num;
+ /// Insertion point for evaluating multi-piece expression.
+ uint64_t op_piece_offset = 0;
+ Value pieces; // Used for DW_OP_piece
+
// Make sure all of the data is available in opcodes.
if (!opcodes.ValidOffsetForDataOfSize(opcodes_offset, opcodes_length))
{
@@ -1363,7 +1394,7 @@ DWARFExpression::Evaluate
if (log && log->GetVerbose())
{
size_t count = stack.size();
- log->Printf("Stack before operation has %zu values:", count);
+ log->Printf("Stack before operation has %" PRIu64 " values:", (uint64_t)count);
for (size_t i=0; i<count; ++i)
{
StreamString new_value;
@@ -1453,14 +1484,11 @@ DWARFExpression::Evaluate
if (process)
{
lldb::addr_t pointer_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
- uint8_t addr_bytes[sizeof(lldb::addr_t)];
- uint32_t addr_size = process->GetAddressByteSize();
Error error;
- if (process->ReadMemory(pointer_addr, &addr_bytes, addr_size, error) == addr_size)
+ lldb::addr_t pointer_value = process->ReadPointerFromMemory(pointer_addr, error);
+ if (pointer_value != LLDB_INVALID_ADDRESS)
{
- DataExtractor addr_data(addr_bytes, sizeof(addr_bytes), process->GetByteOrder(), addr_size);
- lldb::offset_t addr_data_offset = 0;
- stack.back().GetScalar() = addr_data.GetPointer(&addr_data_offset);
+ stack.back().GetScalar() = pointer_value;
stack.back().ClearContext();
}
else
@@ -2574,45 +2602,134 @@ DWARFExpression::Evaluate
// variable a particular DWARF expression refers to.
//----------------------------------------------------------------------
case DW_OP_piece:
- if (stack.size() < 1)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_piece.");
- return false;
- }
- else
{
const uint64_t piece_byte_size = opcodes.GetULEB128(&offset);
- switch (stack.back().GetValueType())
+
+ if (piece_byte_size > 0)
{
- case Value::eValueTypeScalar:
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeHostAddress:
+ Value curr_piece;
+
+ if (stack.empty())
+ {
+ // In a multi-piece expression, this means that the current piece is not available.
+ // Fill with zeros for now by resizing the data and appending it
+ curr_piece.ResizeData(piece_byte_size);
+ ::memset (curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size);
+ pieces.AppendDataToHostBuffer(curr_piece);
+ }
+ else
+ {
+ Error error;
+ // Extract the current piece into "curr_piece"
+ Value curr_piece_source_value(stack.back());
+ stack.pop_back();
+
+ const Value::ValueType curr_piece_source_value_type = curr_piece_source_value.GetValueType();
+ switch (curr_piece_source_value_type)
{
- uint32_t bit_size = piece_byte_size * 8;
- uint32_t bit_offset = 0;
- if (!stack.back().GetScalar().ExtractBitfield (bit_size, bit_offset))
+ case Value::eValueTypeLoadAddress:
+ if (process)
+ {
+ if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size)
+ {
+ lldb::addr_t load_addr = curr_piece_source_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+ if (process->ReadMemory(load_addr, curr_piece.GetBuffer().GetBytes(), piece_byte_size, error) != piece_byte_size)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat ("failed to read memory DW_OP_piece(%" PRIu64 ") from 0x%" PRIx64,
+ piece_byte_size,
+ load_addr);
+ return false;
+ }
+ }
+ else
+ {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat ("failed to resize the piece memory buffer for DW_OP_piece(%" PRIu64 ")", piece_byte_size);
+ return false;
+ }
+ }
+ break;
+
+ case Value::eValueTypeFileAddress:
+ case Value::eValueTypeHostAddress:
+ if (error_ptr)
+ {
+ lldb::addr_t addr = curr_piece_source_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+ error_ptr->SetErrorStringWithFormat ("failed to read memory DW_OP_piece(%" PRIu64 ") from %s address 0x%" PRIx64,
+ piece_byte_size,
+ curr_piece_source_value.GetValueType() == Value::eValueTypeFileAddress ? "file" : "host",
+ addr);
+ }
+ return false;
+
+ case Value::eValueTypeScalar:
+ {
+ uint32_t bit_size = piece_byte_size * 8;
+ uint32_t bit_offset = 0;
+ if (!curr_piece_source_value.GetScalar().ExtractBitfield (bit_size, bit_offset))
+ {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte scalar value.", piece_byte_size, (uint64_t)curr_piece_source_value.GetScalar().GetByteSize());
+ return false;
+ }
+ curr_piece = curr_piece_source_value;
+ }
+ break;
+
+ case Value::eValueTypeVector:
+ {
+ if (curr_piece_source_value.GetVector().length >= piece_byte_size)
+ curr_piece_source_value.GetVector().length = piece_byte_size;
+ else
+ {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte vector value.", piece_byte_size, (uint64_t)curr_piece_source_value.GetVector().length);
+ return false;
+ }
+ }
+ 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?
+ if (op_piece_offset == 0)
+ {
+ // This is the first piece, we should push it back onto the stack so subsequent
+ // pieces will be able to access this piece and add to it
+ if (pieces.AppendDataToHostBuffer(curr_piece) == 0)
{
if (error_ptr)
- error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte scalar value.", piece_byte_size, (uint64_t)stack.back().GetScalar().GetByteSize());
+ error_ptr->SetErrorString("failed to append piece data");
return false;
}
}
- break;
-
- case Value::eValueTypeVector:
+ else if (!stack.empty())
{
- if (stack.back().GetVector().length >= piece_byte_size)
- stack.back().GetVector().length = piece_byte_size;
- else
+ // If this is the second or later piece there should be a value on the stack
+ if (pieces.GetBuffer().GetByteSize() != op_piece_offset)
{
if (error_ptr)
- error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte vector value.", piece_byte_size, (uint64_t)stack.back().GetVector().length);
+ error_ptr->SetErrorStringWithFormat ("DW_OP_piece for offset %" PRIu64 " but top of stack is of size %" PRIu64,
+ op_piece_offset,
+ pieces.GetBuffer().GetByteSize());
+ return false;
+ }
+
+ if (pieces.AppendDataToHostBuffer(curr_piece) == 0)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString("failed to append piece data");
return false;
}
}
- break;
+ op_piece_offset += piece_byte_size;
+ }
}
}
break;
@@ -2631,9 +2748,6 @@ DWARFExpression::Evaluate
switch (stack.back().GetValueType())
{
case Value::eValueTypeScalar:
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeHostAddress:
{
if (!stack.back().GetScalar().ExtractBitfield (piece_bit_size, piece_bit_offset))
{
@@ -2646,11 +2760,22 @@ DWARFExpression::Evaluate
}
}
break;
-
+
+ case Value::eValueTypeFileAddress:
+ case Value::eValueTypeLoadAddress:
+ case Value::eValueTypeHostAddress:
+ if (error_ptr)
+ {
+ error_ptr->SetErrorStringWithFormat ("unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 ", bit_offset = %" PRIu64 ") from an addresss value.",
+ piece_bit_size,
+ piece_bit_offset);
+ }
+ return false;
+
case Value::eValueTypeVector:
if (error_ptr)
{
- error_ptr->SetErrorStringWithFormat ("unable to extract %" PRIu64 " bit value with %" PRIu64 " bit offset from a vector value.",
+ error_ptr->SetErrorStringWithFormat ("unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 ", bit_offset = %" PRIu64 ") from a vector value.",
piece_bit_size,
piece_bit_offset);
}
@@ -2784,7 +2909,7 @@ DWARFExpression::Evaluate
return false;
}
- if (!exe_ctx || !opcode_ctx)
+ if (!exe_ctx || !module_sp)
{
if (error_ptr)
error_ptr->SetErrorString("No context to evaluate TLS within.");
@@ -2800,7 +2925,7 @@ DWARFExpression::Evaluate
}
// Lookup the TLS block address for this thread and module.
- addr_t tls_addr = thread->GetThreadLocalData (opcode_ctx);
+ addr_t tls_addr = thread->GetThreadLocalData (module_sp);
if (tls_addr == LLDB_INVALID_ADDRESS)
{
@@ -2825,24 +2950,34 @@ DWARFExpression::Evaluate
if (stack.empty())
{
- if (error_ptr)
- error_ptr->SetErrorString ("Stack empty after evaluation.");
- return false;
+ // Nothing on the stack, check if we created a piece value from DW_OP_piece or DW_OP_bit_piece opcodes
+ if (pieces.GetBuffer().GetByteSize())
+ {
+ result = pieces;
+ }
+ else
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString ("Stack empty after evaluation.");
+ return false;
+ }
}
- else if (log && log->GetVerbose())
+ else
{
- size_t count = stack.size();
- log->Printf("Stack after operation has %zu values:", count);
- for (size_t i=0; i<count; ++i)
+ if (log && log->GetVerbose())
{
- StreamString new_value;
- new_value.Printf("[%" PRIu64 "]", (uint64_t)i);
- stack[i].Dump(&new_value);
- log->Printf(" %s", new_value.GetData());
+ size_t count = stack.size();
+ log->Printf("Stack after operation has %" PRIu64 " values:", (uint64_t)count);
+ for (size_t i=0; i<count; ++i)
+ {
+ StreamString new_value;
+ new_value.Printf("[%" PRIu64 "]", (uint64_t)i);
+ stack[i].Dump(&new_value);
+ log->Printf(" %s", new_value.GetData());
+ }
}
+ result = stack.back();
}
-
- result = stack.back();
return true; // Return true on success
}
diff --git a/source/Expression/ExpressionSourceCode.cpp b/source/Expression/ExpressionSourceCode.cpp
index aef3b9e301e5..080562e51e91 100644
--- a/source/Expression/ExpressionSourceCode.cpp
+++ b/source/Expression/ExpressionSourceCode.cpp
@@ -10,6 +10,9 @@
#include "lldb/Expression/ExpressionSourceCode.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Platform.h"
+#include "lldb/Target/Target.h"
using namespace lldb_private;
@@ -25,25 +28,45 @@ ExpressionSourceCode::g_expression_prefix = R"(
#define nil (__null)
#define YES ((BOOL)1)
#define NO ((BOOL)0)
-typedef signed char BOOL;
-typedef signed __INT8_TYPE__ int8_t;
-typedef unsigned __INT8_TYPE__ uint8_t;
-typedef signed __INT16_TYPE__ int16_t;
-typedef unsigned __INT16_TYPE__ uint16_t;
-typedef signed __INT32_TYPE__ int32_t;
-typedef unsigned __INT32_TYPE__ uint32_t;
-typedef signed __INT64_TYPE__ int64_t;
-typedef unsigned __INT64_TYPE__ uint64_t;
-typedef signed __INTPTR_TYPE__ intptr_t;
-typedef unsigned __INTPTR_TYPE__ uintptr_t;
+typedef __INT8_TYPE__ int8_t;
+typedef __UINT8_TYPE__ uint8_t;
+typedef __INT16_TYPE__ int16_t;
+typedef __UINT16_TYPE__ uint16_t;
+typedef __INT32_TYPE__ int32_t;
+typedef __UINT32_TYPE__ uint32_t;
+typedef __INT64_TYPE__ int64_t;
+typedef __UINT64_TYPE__ uint64_t;
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __UINTPTR_TYPE__ uintptr_t;
typedef __SIZE_TYPE__ size_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef unsigned short unichar;
)";
-bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method) const
+bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const
{
+ const char *target_specific_defines = "typedef signed char BOOL;\n";
+ static ConstString g_platform_ios_simulator ("PlatformiOSSimulator");
+
+ if (Target *target = exe_ctx.GetTargetPtr())
+ {
+ if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64)
+ {
+ target_specific_defines = "typedef bool BOOL;\n";
+ }
+ if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
+ {
+ if (lldb::PlatformSP platform_sp = target->GetPlatform())
+ {
+ if (platform_sp->GetPluginName() == g_platform_ios_simulator)
+ {
+ target_specific_defines = "typedef bool BOOL;\n";
+ }
+ }
+ }
+ }
+
if (m_wrap)
{
switch (wrapping_language)
@@ -65,12 +88,14 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi
case lldb::eLanguageTypeC:
wrap_stream.Printf("%s \n"
"%s \n"
+ "%s \n"
"void \n"
"%s(void *$__lldb_arg) \n"
"{ \n"
" %s; \n"
"} \n",
g_expression_prefix,
+ target_specific_defines,
m_prefix.c_str(),
m_name.c_str(),
m_body.c_str());
@@ -78,12 +103,14 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi
case lldb::eLanguageTypeC_plus_plus:
wrap_stream.Printf("%s \n"
"%s \n"
+ "%s \n"
"void \n"
"$__lldb_class::%s(void *$__lldb_arg) %s\n"
"{ \n"
" %s; \n"
"} \n",
g_expression_prefix,
+ target_specific_defines,
m_prefix.c_str(),
m_name.c_str(),
(const_object ? "const" : ""),
@@ -94,6 +121,7 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi
{
wrap_stream.Printf("%s \n"
"%s \n"
+ "%s \n"
"@interface $__lldb_objc_class ($__lldb_category) \n"
"+(void)%s:(void *)$__lldb_arg; \n"
"@end \n"
@@ -104,6 +132,7 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi
"} \n"
"@end \n",
g_expression_prefix,
+ target_specific_defines,
m_prefix.c_str(),
m_name.c_str(),
m_name.c_str(),
@@ -113,6 +142,7 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi
{
wrap_stream.Printf("%s \n"
"%s \n"
+ "%s \n"
"@interface $__lldb_objc_class ($__lldb_category) \n"
"-(void)%s:(void *)$__lldb_arg; \n"
"@end \n"
@@ -123,6 +153,7 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi
"} \n"
"@end \n",
g_expression_prefix,
+ target_specific_defines,
m_prefix.c_str(),
m_name.c_str(),
m_name.c_str(),
diff --git a/source/Expression/IRDynamicChecks.cpp b/source/Expression/IRDynamicChecks.cpp
index a75a0fca9c62..aa5d28bb8aad 100644
--- a/source/Expression/IRDynamicChecks.cpp
+++ b/source/Expression/IRDynamicChecks.cpp
@@ -33,7 +33,7 @@ static char ID;
#define VALID_POINTER_CHECK_NAME "$__lldb_valid_pointer_check"
#define VALID_OBJC_OBJECT_CHECK_NAME "$__lldb_objc_object_check"
-static const char g_valid_pointer_check_text[] =
+static const char g_valid_pointer_check_text[] =
"extern \"C\" void\n"
"$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n"
"{\n"
@@ -56,22 +56,22 @@ DynamicCheckerFunctions::Install(Stream &error_stream,
VALID_POINTER_CHECK_NAME));
if (!m_valid_pointer_check->Install(error_stream, exe_ctx))
return false;
-
+
Process *process = exe_ctx.GetProcessPtr();
if (process)
{
ObjCLanguageRuntime *objc_language_runtime = process->GetObjCLanguageRuntime();
-
+
if (objc_language_runtime)
{
m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(VALID_OBJC_OBJECT_CHECK_NAME));
-
+
if (!m_objc_object_check->Install(error_stream, exe_ctx))
return false;
}
}
-
+
return true;
}
@@ -94,7 +94,7 @@ DynamicCheckerFunctions::DoCheckersExplainStop (lldb::addr_t addr, Stream &messa
}
-static std::string
+static std::string
PrintValue(llvm::Value *V, bool truncate = false)
{
std::string s;
@@ -128,10 +128,10 @@ PrintValue(llvm::Value *V, bool truncate = false)
///
/// - InspectInstruction [default: does nothing]
///
-/// - InspectBasicBlock [default: iterates through the instructions in a
+/// - InspectBasicBlock [default: iterates through the instructions in a
/// basic block calling InspectInstruction]
///
-/// - InspectFunction [default: iterates through the basic blocks in a
+/// - InspectFunction [default: iterates through the basic blocks in a
/// function calling InspectBasicBlock]
//----------------------------------------------------------------------
class Instrumenter {
@@ -150,7 +150,7 @@ public:
m_intptr_ty(NULL)
{
}
-
+
virtual~Instrumenter ()
{
}
@@ -168,7 +168,7 @@ public:
{
return InspectFunction(function);
}
-
+
//------------------------------------------------------------------
/// Instrument all the instructions found by Inspect()
///
@@ -184,7 +184,7 @@ public:
if (!InstrumentInstruction(*ii))
return false;
}
-
+
return true;
}
protected:
@@ -192,13 +192,13 @@ protected:
/// Add instrumentation to a single instruction
///
/// @param[in] inst
- /// The instruction to be instrumented.
+ /// The instruction to be instrumented.
///
/// @return
/// True on success; false otherwise.
//------------------------------------------------------------------
virtual bool InstrumentInstruction(llvm::Instruction *inst) = 0;
-
+
//------------------------------------------------------------------
/// Register a single instruction to be instrumented
///
@@ -209,7 +209,7 @@ protected:
{
m_to_instrument.push_back(&i);
}
-
+
//------------------------------------------------------------------
/// Determine whether a single instruction is interesting to
/// instrument, and, if so, call RegisterInstruction
@@ -224,7 +224,7 @@ protected:
{
return true;
}
-
+
//------------------------------------------------------------------
/// Scan a basic block to see if any instructions are interesting
///
@@ -243,15 +243,15 @@ protected:
if (!InspectInstruction(*ii))
return false;
}
-
+
return true;
}
-
+
//------------------------------------------------------------------
/// Scan a function to see if any instructions are interesting
///
/// @param[in] f
- /// The function to be inspected.
+ /// The function to be inspected.
///
/// @return
/// False if there was an error scanning; true otherwise.
@@ -265,12 +265,12 @@ protected:
if (!InspectBasicBlock(*bbi))
return false;
}
-
+
return true;
}
-
+
//------------------------------------------------------------------
- /// Build a function pointer for a function with signature
+ /// Build a function pointer for a function with signature
/// void (*)(uint8_t*) with a given address
///
/// @param[in] start_address
@@ -282,19 +282,19 @@ protected:
llvm::Value *BuildPointerValidatorFunc(lldb::addr_t start_address)
{
llvm::Type *param_array[1];
-
+
param_array[0] = const_cast<llvm::PointerType*>(GetI8PtrTy());
-
+
ArrayRef<llvm::Type*> params(param_array, 1);
-
+
FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true);
PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
Constant *fun_addr_int = ConstantInt::get(GetIntptrTy(), start_address, false);
return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
}
-
+
//------------------------------------------------------------------
- /// Build a function pointer for a function with signature
+ /// Build a function pointer for a function with signature
/// void (*)(uint8_t*, uint8_t*) with a given address
///
/// @param[in] start_address
@@ -306,41 +306,41 @@ protected:
llvm::Value *BuildObjectCheckerFunc(lldb::addr_t start_address)
{
llvm::Type *param_array[2];
-
+
param_array[0] = const_cast<llvm::PointerType*>(GetI8PtrTy());
param_array[1] = const_cast<llvm::PointerType*>(GetI8PtrTy());
-
+
ArrayRef<llvm::Type*> params(param_array, 2);
-
+
FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true);
PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
Constant *fun_addr_int = ConstantInt::get(GetIntptrTy(), start_address, false);
return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
}
-
+
PointerType *GetI8PtrTy()
{
if (!m_i8ptr_ty)
m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
-
+
return m_i8ptr_ty;
}
-
+
IntegerType *GetIntptrTy()
{
if (!m_intptr_ty)
{
llvm::DataLayout data_layout(&m_module);
-
+
m_intptr_ty = llvm::Type::getIntNTy(m_module.getContext(), data_layout.getPointerSizeInBits());
}
-
+
return m_intptr_ty;
}
-
+
typedef std::vector <llvm::Instruction *> InstVector;
typedef InstVector::iterator InstIterator;
-
+
InstVector m_to_instrument; ///< List of instructions the inspector found
llvm::Module &m_module; ///< The module which is being instrumented
DynamicCheckerFunctions &m_checker_functions; ///< The dynamic checker functions for the process
@@ -358,7 +358,7 @@ public:
m_valid_pointer_check_func(NULL)
{
}
-
+
virtual ~ValidPointerChecker ()
{
}
@@ -368,53 +368,53 @@ private:
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
- log->Printf("Instrumenting load/store instruction: %s\n",
+ log->Printf("Instrumenting load/store instruction: %s\n",
PrintValue(inst).c_str());
-
+
if (!m_valid_pointer_check_func)
m_valid_pointer_check_func = BuildPointerValidatorFunc(m_checker_functions.m_valid_pointer_check->StartAddress());
-
+
llvm::Value *dereferenced_ptr = NULL;
-
+
if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst> (inst))
dereferenced_ptr = li->getPointerOperand();
else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst> (inst))
dereferenced_ptr = si->getPointerOperand();
else
return false;
-
+
// Insert an instruction to cast the loaded value to int8_t*
-
+
BitCastInst *bit_cast = new BitCastInst(dereferenced_ptr,
GetI8PtrTy(),
"",
inst);
-
+
// Insert an instruction to call the helper with the result
-
+
llvm::Value *arg_array[1];
-
+
arg_array[0] = bit_cast;
-
+
llvm::ArrayRef<llvm::Value *> args(arg_array, 1);
-
- CallInst::Create(m_valid_pointer_check_func,
+
+ CallInst::Create(m_valid_pointer_check_func,
args,
"",
inst);
-
+
return true;
}
-
+
bool InspectInstruction(llvm::Instruction &i)
{
if (dyn_cast<llvm::LoadInst> (&i) ||
dyn_cast<llvm::StoreInst> (&i))
RegisterInstruction(i);
-
+
return true;
}
-
+
llvm::Value *m_valid_pointer_check_func;
};
@@ -427,12 +427,12 @@ public:
m_objc_object_check_func(NULL)
{
}
-
+
virtual
~ObjcObjectChecker ()
{
}
-
+
enum msgSend_type
{
eMsgSend = 0,
@@ -441,25 +441,25 @@ public:
eMsgSend_fpret,
eMsgSend_stret
};
-
+
std::map <llvm::Instruction *, msgSend_type> msgSend_types;
private:
bool InstrumentInstruction(llvm::Instruction *inst)
{
CallInst *call_inst = dyn_cast<CallInst>(inst);
-
+
if (!call_inst)
return false; // call_inst really shouldn't be NULL, because otherwise InspectInstruction wouldn't have registered it
-
+
if (!m_objc_object_check_func)
m_objc_object_check_func = BuildObjectCheckerFunc(m_checker_functions.m_objc_object_check->StartAddress());
-
+
// id objc_msgSend(id theReceiver, SEL theSelector, ...)
-
+
llvm::Value *target_object;
llvm::Value *selector;
-
+
switch (msgSend_types[inst])
{
case eMsgSend:
@@ -475,119 +475,124 @@ private:
case eMsgSendSuper_stret:
return true;
}
-
+
// These objects should always be valid according to Sean Calannan
assert (target_object);
assert (selector);
// Insert an instruction to cast the receiver id to int8_t*
-
+
BitCastInst *bit_cast = new BitCastInst(target_object,
GetI8PtrTy(),
"",
inst);
-
+
// Insert an instruction to call the helper with the result
-
+
llvm::Value *arg_array[2];
-
+
arg_array[0] = bit_cast;
arg_array[1] = selector;
-
+
ArrayRef<llvm::Value*> args(arg_array, 2);
-
- CallInst::Create(m_objc_object_check_func,
+
+ CallInst::Create(m_objc_object_check_func,
args,
"",
inst);
-
+
return true;
}
-
+
bool InspectInstruction(llvm::Instruction &i)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
CallInst *call_inst = dyn_cast<CallInst>(&i);
-
+
if (call_inst)
{
// This metadata is set by IRForTarget::MaybeHandleCall().
-
+
MDNode *metadata = call_inst->getMetadata("lldb.call.realName");
-
+
if (!metadata)
return true;
-
+
if (metadata->getNumOperands() != 1)
{
if (log)
- log->Printf("Function call metadata has %d operands for [%p] %s", metadata->getNumOperands(), call_inst, PrintValue(call_inst).c_str());
+ log->Printf("Function call metadata has %d operands for [%p] %s",
+ metadata->getNumOperands(),
+ static_cast<void*>(call_inst),
+ PrintValue(call_inst).c_str());
return false;
}
-
+
MDString *real_name = dyn_cast<MDString>(metadata->getOperand(0));
-
+
if (!real_name)
{
if (log)
- log->Printf("Function call metadata is not an MDString for [%p] %s", call_inst, PrintValue(call_inst).c_str());
+ log->Printf("Function call metadata is not an MDString for [%p] %s",
+ static_cast<void*>(call_inst),
+ PrintValue(call_inst).c_str());
return false;
}
std::string name_str = real_name->getString();
const char* name_cstr = name_str.c_str();
-
+
if (log)
log->Printf("Found call to %s: %s\n", name_cstr, PrintValue(call_inst).c_str());
-
+
if (name_str.find("objc_msgSend") == std::string::npos)
return true;
-
+
if (!strcmp(name_cstr, "objc_msgSend"))
{
RegisterInstruction(i);
msgSend_types[&i] = eMsgSend;
return true;
}
-
+
if (!strcmp(name_cstr, "objc_msgSend_stret"))
{
RegisterInstruction(i);
msgSend_types[&i] = eMsgSend_stret;
return true;
}
-
+
if (!strcmp(name_cstr, "objc_msgSend_fpret"))
{
RegisterInstruction(i);
msgSend_types[&i] = eMsgSend_fpret;
return true;
}
-
+
if (!strcmp(name_cstr, "objc_msgSendSuper"))
{
RegisterInstruction(i);
msgSend_types[&i] = eMsgSendSuper;
return true;
}
-
+
if (!strcmp(name_cstr, "objc_msgSendSuper_stret"))
{
RegisterInstruction(i);
msgSend_types[&i] = eMsgSendSuper_stret;
return true;
}
-
+
if (log)
log->Printf("Function name '%s' contains 'objc_msgSend' but is not handled", name_str.c_str());
-
+
return true;
}
-
+
return true;
}
-
+
llvm::Value *m_objc_object_check_func;
};
@@ -607,52 +612,52 @@ bool
IRDynamicChecks::runOnModule(llvm::Module &M)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
llvm::Function* function = M.getFunction(StringRef(m_func_name.c_str()));
-
+
if (!function)
{
if (log)
log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
-
+
return false;
}
if (m_checker_functions.m_valid_pointer_check.get())
{
ValidPointerChecker vpc(M, m_checker_functions);
-
+
if (!vpc.Inspect(*function))
return false;
-
+
if (!vpc.Instrument())
return false;
}
-
+
if (m_checker_functions.m_objc_object_check.get())
{
ObjcObjectChecker ooc(M, m_checker_functions);
-
+
if (!ooc.Inspect(*function))
return false;
-
+
if (!ooc.Instrument())
return false;
}
-
+
if (log && log->GetVerbose())
{
std::string s;
raw_string_ostream oss(s);
-
+
M.print(oss, NULL);
-
+
oss.flush();
-
+
log->Printf ("Module after dynamic checks: \n%s", s.c_str());
}
-
- return true;
+
+ return true;
}
void
diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp
index 17bd03ae6cb5..090f88fc1bfe 100644
--- a/source/Expression/IRExecutionUnit.cpp
+++ b/source/Expression/IRExecutionUnit.cpp
@@ -7,18 +7,16 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
-// Project includes
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Section.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
@@ -46,39 +44,39 @@ lldb::addr_t
IRExecutionUnit::WriteNow (const uint8_t *bytes,
size_t size,
Error &error)
-{
+{
lldb::addr_t allocation_process_addr = Malloc (size,
8,
lldb::ePermissionsWritable | lldb::ePermissionsReadable,
eAllocationPolicyMirror,
error);
-
+
if (!error.Success())
return LLDB_INVALID_ADDRESS;
-
+
WriteMemory(allocation_process_addr, bytes, size, error);
-
+
if (!error.Success())
{
Error err;
Free (allocation_process_addr, err);
-
+
return LLDB_INVALID_ADDRESS;
}
-
+
if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
{
DataBufferHeap my_buffer(size, 0);
Error err;
ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err);
-
+
if (err.Success())
{
DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8);
my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), allocation_process_addr, 16, DataExtractor::TypeUInt8);
}
}
-
+
return allocation_process_addr;
}
@@ -87,9 +85,9 @@ IRExecutionUnit::FreeNow (lldb::addr_t allocation)
{
if (allocation == LLDB_INVALID_ADDRESS)
return;
-
+
Error err;
-
+
Free(allocation, err);
}
@@ -98,16 +96,16 @@ IRExecutionUnit::DisassembleFunction (Stream &stream,
lldb::ProcessSP &process_wp)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
ExecutionContext exe_ctx(process_wp);
-
+
Error ret;
-
+
ret.Clear();
-
+
lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
-
+
for (JittedFunction &function : m_jitted_functions)
{
if (strstr(function.m_name.c_str(), m_name.AsCString()))
@@ -116,31 +114,31 @@ IRExecutionUnit::DisassembleFunction (Stream &stream,
func_remote_addr = function.m_remote_addr;
}
}
-
+
if (func_local_addr == LLDB_INVALID_ADDRESS)
{
ret.SetErrorToGenericError();
ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString());
return ret;
}
-
+
if (log)
log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
-
+
std::pair <lldb::addr_t, lldb::addr_t> func_range;
-
+
func_range = GetRemoteRangeForLocal(func_local_addr);
-
+
if (func_range.first == 0 && func_range.second == 0)
{
ret.SetErrorToGenericError();
ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString());
return ret;
}
-
+
if (log)
log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second);
-
+
Target *target = exe_ctx.GetTargetPtr();
if (!target)
{
@@ -148,44 +146,44 @@ IRExecutionUnit::DisassembleFunction (Stream &stream,
ret.SetErrorString("Couldn't find the target");
return ret;
}
-
+
lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));
-
+
Process *process = exe_ctx.GetProcessPtr();
Error err;
process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
-
+
if (!err.Success())
{
ret.SetErrorToGenericError();
ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
return ret;
}
-
+
ArchSpec arch(target->GetArchitecture());
-
+
const char *plugin_name = NULL;
const char *flavor_string = NULL;
lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(arch, flavor_string, plugin_name);
-
+
if (!disassembler_sp)
{
ret.SetErrorToGenericError();
ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
return ret;
}
-
+
if (!process)
{
ret.SetErrorToGenericError();
ret.SetErrorString("Couldn't find the process");
return ret;
}
-
+
DataExtractor extractor(buffer_sp,
process->GetByteOrder(),
target->GetArchitecture().GetAddressByteSize());
-
+
if (log)
{
log->Printf("Function data has contents:");
@@ -196,12 +194,12 @@ IRExecutionUnit::DisassembleFunction (Stream &stream,
16,
DataExtractor::TypeUInt8);
}
-
+
disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false);
-
+
InstructionList &instruction_list = disassembler_sp->GetInstructionList();
const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
-
+
for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize();
instruction_index < num_instructions;
++instruction_index)
@@ -223,7 +221,7 @@ IRExecutionUnit::DisassembleFunction (Stream &stream,
static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic, void *Context, unsigned LocCookie)
{
Error *err = static_cast<Error*>(Context);
-
+
if (err && err->Success())
{
err->SetErrorToGenericError();
@@ -237,52 +235,52 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
lldb::addr_t &func_end)
{
lldb::ProcessSP process_sp(GetProcessWP().lock());
-
+
static Mutex s_runnable_info_mutex(Mutex::Type::eMutexTypeRecursive);
-
+
func_addr = LLDB_INVALID_ADDRESS;
func_end = LLDB_INVALID_ADDRESS;
-
+
if (!process_sp)
{
error.SetErrorToGenericError();
error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid");
return;
}
-
+
if (m_did_jit)
{
func_addr = m_function_load_addr;
func_end = m_function_end_load_addr;
-
+
return;
};
-
+
Mutex::Locker runnable_info_mutex_locker(s_runnable_info_mutex);
-
+
m_did_jit = true;
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
std::string error_string;
-
+
if (log)
{
std::string s;
llvm::raw_string_ostream oss(s);
-
+
m_module->print(oss, NULL);
-
+
oss.flush();
-
+
log->Printf ("Module being sent to JIT: \n%s", s.c_str());
}
-
+
llvm::Triple triple(m_module->getTargetTriple());
llvm::Function *function = m_module->getFunction (m_name.AsCString());
llvm::Reloc::Model relocModel;
llvm::CodeModel::Model codeModel;
-
+
if (triple.isOSBinFormatELF())
{
relocModel = llvm::Reloc::Static;
@@ -294,11 +292,11 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
relocModel = llvm::Reloc::PIC_;
codeModel = llvm::CodeModel::Small;
}
-
+
m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);
-
- llvm::EngineBuilder builder(m_module_ap.get());
-
+
+ llvm::EngineBuilder builder(std::move(m_module_ap));
+
builder.setEngineKind(llvm::EngineKind::JIT)
.setErrorStr(&error_string)
.setRelocationModel(relocModel)
@@ -307,68 +305,67 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
.setAllocateGVsWithCode(true)
.setCodeModel(codeModel)
.setUseMCJIT(true);
-
+
llvm::StringRef mArch;
llvm::StringRef mCPU;
llvm::SmallVector<std::string, 0> mAttrs;
-
+
for (std::string &feature : m_cpu_features)
mAttrs.push_back(feature);
-
+
llvm::TargetMachine *target_machine = builder.selectTarget(triple,
mArch,
mCPU,
mAttrs);
-
+
m_execution_engine_ap.reset(builder.create(target_machine));
-
+
if (!m_execution_engine_ap.get())
{
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
return;
}
- else
- {
- m_module_ap.release(); // ownership was transferred
- }
-
+
+ // Make sure we see all sections, including ones that don't have relocations...
+ m_execution_engine_ap->setProcessAllSections(true);
+
m_execution_engine_ap->DisableLazyCompilation();
-
+
// We don't actually need the function pointer here, this just forces it to get resolved.
-
+
void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function);
-
+
if (!error.Success())
{
// We got an error through our callback!
return;
}
-
+
if (!function)
{
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString());
return;
}
-
+
if (!fun_ptr)
{
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString());
return;
}
-
+
m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr));
-
+
CommitAllocations(process_sp);
ReportAllocations(*m_execution_engine_ap);
WriteData(process_sp);
-
+
for (JittedFunction &jitted_function : m_jitted_functions)
{
jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);
-
+
if (!jitted_function.m_name.compare(m_name.AsCString()))
{
AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr);
@@ -376,15 +373,15 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
m_function_load_addr = jitted_function.m_remote_addr;
}
}
-
+
if (log)
{
log->Printf("Code can be run in the target.");
-
+
StreamString disassembly_stream;
-
+
Error err = DisassembleFunction(disassembly_stream, process_sp);
-
+
if (!err.Success())
{
log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
@@ -393,18 +390,18 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
{
log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
}
-
+
log->Printf("Sections: ");
for (AllocationRecord &record : m_records)
{
if (record.m_process_address != LLDB_INVALID_ADDRESS)
{
record.dump(log);
-
+
DataBufferHeap my_buffer(record.m_size, 0);
Error err;
ReadMemory(my_buffer.GetBytes(), record.m_process_address, record.m_size, err);
-
+
if (err.Success())
{
DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8);
@@ -413,10 +410,10 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
}
}
}
-
+
func_addr = m_function_load_addr;
func_end = m_function_end_load_addr;
-
+
return;
}
@@ -433,6 +430,9 @@ IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) :
{
}
+IRExecutionUnit::MemoryManager::~MemoryManager ()
+{
+}
void
IRExecutionUnit::MemoryManager::setMemoryWritable ()
{
@@ -464,15 +464,19 @@ IRExecutionUnit::MemoryManager::allocateStub(const llvm::GlobalValue* F,
m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Stub),
StubSize,
- Alignment));
+ Alignment,
+ eSectionIDInvalid,
+ NULL));
if (log)
{
log->Printf("IRExecutionUnit::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p",
- F, StubSize, Alignment, return_value);
+ static_cast<const void*>(F), StubSize, Alignment,
+ static_cast<void*>(return_value));
}
-
+
return return_value;
}
@@ -484,24 +488,136 @@ IRExecutionUnit::MemoryManager::endFunctionBody(const llvm::Function *F,
m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd);
}
+lldb::SectionType
+IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind)
+{
+ lldb::SectionType sect_type = lldb::eSectionTypeCode;
+ switch (alloc_kind)
+ {
+ case AllocationKind::Stub: sect_type = lldb::eSectionTypeCode; break;
+ case AllocationKind::Code: sect_type = lldb::eSectionTypeCode; break;
+ case AllocationKind::Data: sect_type = lldb::eSectionTypeData; break;
+ case AllocationKind::Global:sect_type = lldb::eSectionTypeData; break;
+ case AllocationKind::Bytes: sect_type = lldb::eSectionTypeOther; break;
+ }
+
+ if (!name.empty())
+ {
+ if (name.equals("__text") || name.equals(".text"))
+ sect_type = lldb::eSectionTypeCode;
+ else if (name.equals("__data") || name.equals(".data"))
+ sect_type = lldb::eSectionTypeCode;
+ else if (name.startswith("__debug_") || name.startswith(".debug_"))
+ {
+ const uint32_t name_idx = name[0] == '_' ? 8 : 7;
+ llvm::StringRef dwarf_name(name.substr(name_idx));
+ switch (dwarf_name[0])
+ {
+ case 'a':
+ if (dwarf_name.equals("abbrev"))
+ sect_type = lldb::eSectionTypeDWARFDebugAbbrev;
+ else if (dwarf_name.equals("aranges"))
+ sect_type = lldb::eSectionTypeDWARFDebugAranges;
+ break;
+
+ case 'f':
+ if (dwarf_name.equals("frame"))
+ sect_type = lldb::eSectionTypeDWARFDebugFrame;
+ break;
+
+ case 'i':
+ if (dwarf_name.equals("info"))
+ sect_type = lldb::eSectionTypeDWARFDebugInfo;
+ break;
+
+ case 'l':
+ if (dwarf_name.equals("line"))
+ sect_type = lldb::eSectionTypeDWARFDebugLine;
+ else if (dwarf_name.equals("loc"))
+ sect_type = lldb::eSectionTypeDWARFDebugLoc;
+ break;
+
+ case 'm':
+ if (dwarf_name.equals("macinfo"))
+ sect_type = lldb::eSectionTypeDWARFDebugMacInfo;
+ break;
+
+ case 'p':
+ if (dwarf_name.equals("pubnames"))
+ sect_type = lldb::eSectionTypeDWARFDebugPubNames;
+ else if (dwarf_name.equals("pubtypes"))
+ sect_type = lldb::eSectionTypeDWARFDebugPubTypes;
+ break;
+
+ case 's':
+ if (dwarf_name.equals("str"))
+ sect_type = lldb::eSectionTypeDWARFDebugStr;
+ break;
+
+ case 'r':
+ if (dwarf_name.equals("ranges"))
+ sect_type = lldb::eSectionTypeDWARFDebugRanges;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (name.startswith("__apple_") || name.startswith(".apple_"))
+ {
+#if 0
+ const uint32_t name_idx = name[0] == '_' ? 8 : 7;
+ llvm::StringRef apple_name(name.substr(name_idx));
+ switch (apple_name[0])
+ {
+ case 'n':
+ if (apple_name.equals("names"))
+ sect_type = lldb::eSectionTypeDWARFAppleNames;
+ else if (apple_name.equals("namespac") || apple_name.equals("namespaces"))
+ sect_type = lldb::eSectionTypeDWARFAppleNamespaces;
+ break;
+ case 't':
+ if (apple_name.equals("types"))
+ sect_type = lldb::eSectionTypeDWARFAppleTypes;
+ break;
+ case 'o':
+ if (apple_name.equals("objc"))
+ sect_type = lldb::eSectionTypeDWARFAppleObjC;
+ break;
+ default:
+ break;
+ }
+#else
+ sect_type = lldb::eSectionTypeInvalid;
+#endif
+ }
+ else if (name.equals("__objc_imageinfo"))
+ sect_type = lldb::eSectionTypeOther;
+ }
+ 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));
-
+ Alignment,
+ eSectionIDInvalid,
+ NULL));
+
if (log)
{
log->Printf("IRExecutionUnit::allocateSpace(Size=%" PRIu64 ", Alignment=%u) = %p",
(uint64_t)Size, Alignment, return_value);
}
-
+
return return_value;
}
@@ -512,21 +628,23 @@ IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size,
llvm::StringRef SectionName)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID, SectionName);
-
+
m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
lldb::ePermissionsReadable | lldb::ePermissionsExecutable,
+ GetSectionTypeFromSectionName (SectionName, AllocationKind::Code),
Size,
Alignment,
- SectionID));
-
+ SectionID,
+ SectionName.str().c_str()));
+
if (log)
{
log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
(uint64_t)Size, Alignment, SectionID, return_value);
}
-
+
return return_value;
}
@@ -540,19 +658,21 @@ IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size,
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly);
-
+
m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ lldb::ePermissionsReadable | (IsReadOnly ? 0 : lldb::ePermissionsWritable),
+ GetSectionTypeFromSectionName (SectionName, AllocationKind::Data),
Size,
Alignment,
- SectionID));
+ SectionID,
+ SectionName.str().c_str()));
if (log)
{
log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
(uint64_t)Size, Alignment, SectionID, return_value);
}
-
- return return_value;
+
+ return return_value;
}
uint8_t *
@@ -562,18 +682,21 @@ IRExecutionUnit::MemoryManager::allocateGlobal(uintptr_t Size,
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));
-
+ Alignment,
+ eSectionIDInvalid,
+ NULL));
+
if (log)
{
log->Printf("IRExecutionUnit::allocateGlobal(Size=0x%" PRIx64 ", Alignment=%u) = %p",
(uint64_t)Size, Alignment, return_value);
}
-
+
return return_value;
}
@@ -595,9 +718,9 @@ IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address)
{
if (record.m_process_address == LLDB_INVALID_ADDRESS)
return LLDB_INVALID_ADDRESS;
-
+
lldb::addr_t ret = record.m_process_address + (local_address - record.m_host_address);
-
+
if (log)
{
log->Printf("IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64 " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64 " from [0x%" PRIx64 "..0x%" PRIx64 "].",
@@ -608,7 +731,7 @@ IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address)
record.m_process_address,
record.m_process_address + record.m_size);
}
-
+
return ret;
}
}
@@ -626,11 +749,11 @@ IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address)
{
if (record.m_process_address == LLDB_INVALID_ADDRESS)
return AddrRange(0, 0);
-
+
return AddrRange(record.m_process_address, record.m_size);
}
}
-
+
return AddrRange (0, 0);
}
@@ -638,28 +761,50 @@ bool
IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
{
bool ret = true;
-
+
lldb_private::Error err;
-
+
for (AllocationRecord &record : m_records)
{
if (record.m_process_address != LLDB_INVALID_ADDRESS)
continue;
-
-
- record.m_process_address = Malloc(record.m_size,
- record.m_alignment,
- record.m_permissions,
- eAllocationPolicyProcessOnly,
- err);
-
+
+ switch (record.m_sect_type)
+ {
+ case lldb::eSectionTypeInvalid:
+ case lldb::eSectionTypeDWARFDebugAbbrev:
+ case lldb::eSectionTypeDWARFDebugAranges:
+ case lldb::eSectionTypeDWARFDebugFrame:
+ case lldb::eSectionTypeDWARFDebugInfo:
+ case lldb::eSectionTypeDWARFDebugLine:
+ case lldb::eSectionTypeDWARFDebugLoc:
+ case lldb::eSectionTypeDWARFDebugMacInfo:
+ case lldb::eSectionTypeDWARFDebugPubNames:
+ case lldb::eSectionTypeDWARFDebugPubTypes:
+ case lldb::eSectionTypeDWARFDebugRanges:
+ case lldb::eSectionTypeDWARFDebugStr:
+ case lldb::eSectionTypeDWARFAppleNames:
+ case lldb::eSectionTypeDWARFAppleTypes:
+ case lldb::eSectionTypeDWARFAppleNamespaces:
+ case lldb::eSectionTypeDWARFAppleObjC:
+ err.Clear();
+ break;
+ default:
+ record.m_process_address = Malloc (record.m_size,
+ record.m_alignment,
+ record.m_permissions,
+ eAllocationPolicyProcessOnly,
+ err);
+ break;
+ }
+
if (!err.Success())
{
ret = false;
break;
}
}
-
+
if (!ret)
{
for (AllocationRecord &record : m_records)
@@ -671,7 +816,7 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
}
}
}
-
+
return ret;
}
@@ -682,13 +827,13 @@ IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
{
if (record.m_process_address == LLDB_INVALID_ADDRESS)
continue;
-
+
if (record.m_section_id == eSectionIDInvalid)
continue;
-
+
engine.mapSectionAddress((void*)record.m_host_address, record.m_process_address);
}
-
+
// Trigger re-application of relocations.
engine.finalizeObject();
}
@@ -696,25 +841,26 @@ IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
bool
IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp)
{
+ bool wrote_something = false;
for (AllocationRecord &record : m_records)
{
- if (record.m_process_address == LLDB_INVALID_ADDRESS)
- return false;
-
- lldb_private::Error err;
-
- WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err);
+ if (record.m_process_address != LLDB_INVALID_ADDRESS)
+ {
+ lldb_private::Error err;
+ WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err);
+ if (err.Success())
+ wrote_something = true;
+ }
}
-
- return true;
+ return wrote_something;
}
-void
+void
IRExecutionUnit::AllocationRecord::dump (Log *log)
{
if (!log)
return;
-
+
log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)",
(unsigned long long)m_host_address,
(unsigned long long)m_size,
@@ -722,3 +868,80 @@ IRExecutionUnit::AllocationRecord::dump (Log *log)
(unsigned)m_alignment,
(unsigned)m_section_id);
}
+
+
+lldb::ByteOrder
+IRExecutionUnit::GetByteOrder () const
+{
+ ExecutionContext exe_ctx (GetBestExecutionContextScope());
+ return exe_ctx.GetByteOrder();
+}
+
+uint32_t
+IRExecutionUnit::GetAddressByteSize () const
+{
+ ExecutionContext exe_ctx (GetBestExecutionContextScope());
+ return exe_ctx.GetAddressByteSize();
+}
+
+void
+IRExecutionUnit::PopulateSymtab (lldb_private::ObjectFile *obj_file,
+ lldb_private::Symtab &symtab)
+{
+ // No symbols yet...
+}
+
+
+void
+IRExecutionUnit::PopulateSectionList (lldb_private::ObjectFile *obj_file,
+ lldb_private::SectionList &section_list)
+{
+ for (AllocationRecord &record : m_records)
+ {
+ if (record.m_size > 0)
+ {
+ lldb::SectionSP section_sp (new lldb_private::Section (obj_file->GetModule(),
+ obj_file,
+ record.m_section_id,
+ ConstString(record.m_name),
+ record.m_sect_type,
+ record.m_process_address,
+ record.m_size,
+ record.m_host_address, // file_offset (which is the host address for the data)
+ record.m_size, // file_size
+ 0,
+ record.m_permissions)); // flags
+ section_list.AddSection (section_sp);
+ }
+ }
+}
+
+bool
+IRExecutionUnit::GetArchitecture (lldb_private::ArchSpec &arch)
+{
+ ExecutionContext exe_ctx (GetBestExecutionContextScope());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ arch = target->GetArchitecture();
+ else
+ arch.Clear();
+ return arch.IsValid();
+}
+
+lldb::ModuleSP
+IRExecutionUnit::GetJITModule ()
+{
+ ExecutionContext exe_ctx (GetBestExecutionContextScope());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ {
+ lldb::ModuleSP jit_module_sp = lldb_private::Module::CreateJITModule (std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>(shared_from_this()));
+ if (jit_module_sp)
+ {
+ bool changed = false;
+ jit_module_sp->SetLoadAddress(*target, 0, true, changed);
+ }
+ return jit_module_sp;
+ }
+ return lldb::ModuleSP();
+}
diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp
index a998896a98fd..b91e1b46f88e 100644
--- a/source/Expression/IRForTarget.cpp
+++ b/source/Expression/IRForTarget.cpp
@@ -59,7 +59,7 @@ IRForTarget::FunctionValueCache::~FunctionValueCache()
}
llvm::Value *IRForTarget::FunctionValueCache::GetValue(llvm::Function *function)
-{
+{
if (!m_values.count(function))
{
llvm::Value *ret = m_maker(function);
@@ -72,13 +72,13 @@ llvm::Value *IRForTarget::FunctionValueCache::GetValue(llvm::Function *function)
lldb::addr_t IRForTarget::StaticDataAllocator::Allocate()
{
lldb_private::Error err;
-
+
if (m_allocation != LLDB_INVALID_ADDRESS)
{
m_execution_unit.FreeNow(m_allocation);
m_allocation = LLDB_INVALID_ADDRESS;
}
-
+
m_allocation = m_execution_unit.WriteNow((const uint8_t*)m_stream_string.GetData(), m_stream_string.GetSize(), err);
return m_allocation;
@@ -88,7 +88,7 @@ static llvm::Value *FindEntryInstruction (llvm::Function *function)
{
if (function->empty())
return NULL;
-
+
return function->getEntryBlock().getFirstNonPHIOrDbg();
}
@@ -116,7 +116,7 @@ IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
/* Handy utility functions used at several places in the code */
-static std::string
+static std::string
PrintValue(const Value *value, bool truncate = false)
{
std::string s;
@@ -151,38 +151,38 @@ bool
IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function)
{
llvm_function.setLinkage(GlobalValue::ExternalLinkage);
-
+
std::string name = llvm_function.getName().str();
-
+
return true;
}
-bool
+IRForTarget::LookupResult
IRForTarget::GetFunctionAddress (llvm::Function *fun,
uint64_t &fun_addr,
lldb_private::ConstString &name,
Constant **&value_ptr)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
fun_addr = LLDB_INVALID_ADDRESS;
name.Clear();
value_ptr = NULL;
-
+
if (fun->isIntrinsic())
{
Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID();
-
+
switch (intrinsic_id)
{
default:
if (log)
log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str());
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str());
-
- return false;
+
+ return LookupResult::Fail;
case Intrinsic::memcpy:
{
static lldb_private::ConstString g_memcpy_str ("memcpy");
@@ -195,8 +195,11 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
name = g_memset_str;
}
break;
+ case Intrinsic::dbg_declare:
+ case Intrinsic::dbg_value:
+ return LookupResult::Ignore;
}
-
+
if (log && name)
log->Printf("Resolved intrinsic name \"%s\"", name.GetCString());
}
@@ -204,14 +207,14 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
{
name.SetCStringWithLength (fun->getName().data(), fun->getName().size());
}
-
+
// Find the address of the function.
-
+
clang::NamedDecl *fun_decl = DeclForGlobal (fun);
-
+
if (fun_decl)
{
- if (!m_decl_map->GetFunctionInfo (fun_decl, fun_addr))
+ if (!m_decl_map->GetFunctionInfo (fun_decl, fun_addr))
{
lldb_private::ConstString altnernate_name;
bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr);
@@ -228,7 +231,7 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
found_it = m_decl_map->GetFunctionAddress (altnernate_name, fun_addr);
}
}
-
+
if (!found_it)
{
lldb_private::Mangled mangled_name(name);
@@ -243,7 +246,7 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
log->Printf("Function \"%s\" had no address",
mangled_name.GetName().GetCString());
}
-
+
if (m_error_stream)
{
if (alt_mangled_name)
@@ -258,28 +261,28 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n",
mangled_name.GetName().GetCString());
}
- return false;
+ return LookupResult::Fail;
}
}
}
- else
+ else
{
if (!m_decl_map->GetFunctionAddress (name, fun_addr))
{
if (log)
log->Printf ("Metadataless function \"%s\" had no address", name.GetCString());
-
+
if (m_error_stream)
m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", name.GetCString());
-
- return false;
+
+ return LookupResult::Fail;
}
}
-
+
if (log)
log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), fun_addr);
-
- return true;
+
+ return LookupResult::Success;
}
llvm::Constant *
@@ -293,15 +296,11 @@ IRForTarget::BuildFunctionPointer (llvm::Type *type,
void
IRForTarget::RegisterFunctionMetadata(LLVMContext &context,
- llvm::Value *function_ptr,
+ llvm::Value *function_ptr,
const char *name)
{
- for (Value::use_iterator i = function_ptr->use_begin(), e = function_ptr->use_end();
- i != e;
- ++i)
+ for (llvm::User *user : function_ptr->users())
{
- Value *user = *i;
-
if (Instruction *user_inst = dyn_cast<Instruction>(user))
{
MDString* md_name = MDString::get(context, StringRef(name));
@@ -317,62 +316,74 @@ IRForTarget::RegisterFunctionMetadata(LLVMContext &context,
}
}
-bool
+bool
IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
for (llvm::Module::iterator fi = llvm_module.begin();
fi != llvm_module.end();
++fi)
{
Function *fun = fi;
-
+
bool is_decl = fun->isDeclaration();
-
+
if (log)
log->Printf("Examining %s function %s", (is_decl ? "declaration" : "non-declaration"), fun->getName().str().c_str());
-
+
if (!is_decl)
continue;
-
- if (fun->hasNUses(0))
+
+ if (fun->use_empty())
continue; // ignore
-
+
uint64_t addr = LLDB_INVALID_ADDRESS;
lldb_private::ConstString name;
Constant **value_ptr = NULL;
-
- if (!GetFunctionAddress(fun,
- addr,
- name,
- value_ptr))
+
+ LookupResult result = GetFunctionAddress(fun,
+ addr,
+ name,
+ value_ptr);
+
+ switch (result)
+ {
+ case LookupResult::Fail:
return false; // GetFunctionAddress reports its own errors
-
- Constant *value = BuildFunctionPointer(fun->getFunctionType(), addr);
-
- RegisterFunctionMetadata (llvm_module.getContext(), fun, name.AsCString());
-
- if (value_ptr)
- *value_ptr = value;
-
- // If we are replacing a function with the nobuiltin attribute, it may
- // be called with the builtin attribute on call sites. Remove any such
- // attributes since it's illegal to have a builtin call to something
- // other than a nobuiltin function.
- if (fun->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
- llvm::Attribute builtin = llvm::Attribute::get(fun->getContext(), llvm::Attribute::Builtin);
-
- for (auto u = fun->use_begin(), e = fun->use_end(); u != e; ++u) {
- if (auto call = dyn_cast<CallInst>(*u)) {
- call->removeAttribute(AttributeSet::FunctionIndex, builtin);
+
+ case LookupResult::Ignore:
+ break; // Nothing to do
+
+ case LookupResult::Success:
+ {
+ Constant *value = BuildFunctionPointer(fun->getFunctionType(), addr);
+
+ RegisterFunctionMetadata (llvm_module.getContext(), fun, name.AsCString());
+
+ if (value_ptr)
+ *value_ptr = value;
+
+ // If we are replacing a function with the nobuiltin attribute, it may
+ // be called with the builtin attribute on call sites. Remove any such
+ // attributes since it's illegal to have a builtin call to something
+ // other than a nobuiltin function.
+ if (fun->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
+ llvm::Attribute builtin = llvm::Attribute::get(fun->getContext(), llvm::Attribute::Builtin);
+
+ for (auto u : fun->users()) {
+ if (auto call = dyn_cast<CallInst>(u)) {
+ call->removeAttribute(AttributeSet::FunctionIndex, builtin);
+ }
+ }
}
+
+ fun->replaceAllUsesWith(value);
}
+ break;
}
-
- fun->replaceAllUsesWith(value);
}
-
+
return true;
}
@@ -381,69 +392,69 @@ clang::NamedDecl *
IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module)
{
NamedMDNode *named_metadata = module->getNamedMetadata("clang.global.decl.ptrs");
-
+
if (!named_metadata)
return NULL;
-
+
unsigned num_nodes = named_metadata->getNumOperands();
unsigned node_index;
-
+
for (node_index = 0;
node_index < num_nodes;
++node_index)
{
MDNode *metadata_node = named_metadata->getOperand(node_index);
-
+
if (!metadata_node)
return NULL;
-
+
if (metadata_node->getNumOperands() != 2)
continue;
-
+
if (metadata_node->getOperand(0) != global_val)
continue;
-
+
ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1));
-
+
if (!constant_int)
return NULL;
-
+
uintptr_t ptr = constant_int->getZExtValue();
-
+
return reinterpret_cast<clang::NamedDecl *>(ptr);
}
-
+
return NULL;
}
clang::NamedDecl *
IRForTarget::DeclForGlobal (GlobalValue *global_val)
-{
+{
return DeclForGlobal(global_val, m_module);
}
-bool
+bool
IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (!m_resolve_vars)
return true;
-
+
// Find the result variable. If it doesn't exist, we can give up right here.
-
+
ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable();
-
+
std::string result_name_str;
const char *result_name = NULL;
-
+
for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
vi != ve;
++vi)
{
result_name_str = vi->first().str();
const char *value_name = result_name_str.c_str();
-
+
if (strstr(value_name, "$__lldb_expr_result_ptr") &&
strncmp(value_name, "_ZGV", 4))
{
@@ -451,7 +462,7 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
m_result_is_pointer = true;
break;
}
-
+
if (strstr(value_name, "$__lldb_expr_result") &&
strncmp(value_name, "_ZGV", 4))
{
@@ -460,105 +471,105 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
break;
}
}
-
+
if (!result_name)
{
if (log)
log->PutCString("Couldn't find result variable");
-
+
return true;
}
-
+
if (log)
log->Printf("Result name: \"%s\"", result_name);
-
+
Value *result_value = m_module->getNamedValue(result_name);
-
+
if (!result_value)
{
if (log)
log->PutCString("Result variable had no data");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Result variable's name (%s) exists, but not its definition\n", result_name);
-
+
return false;
}
-
+
if (log)
log->Printf("Found result in the IR: \"%s\"", PrintValue(result_value, false).c_str());
-
+
GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value);
-
+
if (!result_global)
{
if (log)
log->PutCString("Result variable isn't a GlobalVariable");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) is defined, but is not a global variable\n", result_name);
-
+
return false;
}
-
+
clang::NamedDecl *result_decl = DeclForGlobal (result_global);
if (!result_decl)
{
if (log)
log->PutCString("Result variable doesn't have a corresponding Decl");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity\n", result_name);
-
+
return false;
}
-
+
if (log)
{
std::string decl_desc_str;
raw_string_ostream decl_desc_stream(decl_desc_str);
result_decl->print(decl_desc_stream);
decl_desc_stream.flush();
-
+
log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str());
}
-
+
clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl);
if (!result_var)
{
if (log)
log->PutCString("Result variable Decl isn't a VarDecl");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable\n", result_name);
-
+
return false;
}
-
+
// Get the next available result name from m_decl_map and create the persistent
// variable for it
-
+
// If the result is an Lvalue, it is emitted as a pointer; see
// ASTResultSynthesizer::SynthesizeBodyResult.
if (m_result_is_pointer)
{
clang::QualType pointer_qual_type = result_var->getType();
const clang::Type *pointer_type = pointer_qual_type.getTypePtr();
-
+
const clang::PointerType *pointer_pointertype = pointer_type->getAs<clang::PointerType>();
const clang::ObjCObjectPointerType *pointer_objcobjpointertype = pointer_type->getAs<clang::ObjCObjectPointerType>();
-
+
if (pointer_pointertype)
{
clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
-
+
m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
&result_decl->getASTContext());
}
else if (pointer_objcobjpointertype)
{
clang::QualType element_qual_type = clang::QualType(pointer_objcobjpointertype->getObjectType(), 0);
-
+
m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
&result_decl->getASTContext());
}
@@ -566,10 +577,10 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
{
if (log)
log->PutCString("Expected result to have pointer type, but it did not");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Lvalue result (%s) is not a pointer variable\n", result_name);
-
+
return false;
}
}
@@ -578,99 +589,99 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(),
&result_decl->getASTContext());
}
-
+
if (m_result_type.GetBitSize() == 0)
{
lldb_private::StreamString type_desc_stream;
m_result_type.DumpTypeDescription(&type_desc_stream);
-
+
if (log)
log->Printf("Result type has size 0");
-
+
if (m_error_stream)
- m_error_stream->Printf("Error [IRForTarget]: Size of result type '%s' couldn't be determined\n",
+ m_error_stream->Printf("Error [IRForTarget]: Size of result type '%s' couldn't be determined\n",
type_desc_stream.GetData());
return false;
}
-
+
if (log)
{
lldb_private::StreamString type_desc_stream;
m_result_type.DumpTypeDescription(&type_desc_stream);
-
+
log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData());
}
-
+
m_result_name = lldb_private::ConstString("$RESULT_NAME");
-
+
if (log)
log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64,
m_result_name.GetCString(),
m_result_type.GetByteSize());
-
+
// Construct a new result global and set up its metadata
-
- GlobalVariable *new_result_global = new GlobalVariable((*m_module),
+
+ GlobalVariable *new_result_global = new GlobalVariable((*m_module),
result_global->getType()->getElementType(),
false, /* not constant */
GlobalValue::ExternalLinkage,
NULL, /* no initializer */
m_result_name.GetCString ());
-
+
// It's too late in compilation to create a new VarDecl for this, but we don't
// need to. We point the metadata at the old VarDecl. This creates an odd
// anomaly: a variable with a Value whose name is something like $0 and a
// Decl whose name is $__lldb_expr_result. This condition is handled in
// ClangExpressionDeclMap::DoMaterialize, and the name of the variable is
// fixed up.
-
+
ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()),
reinterpret_cast<uint64_t>(result_decl),
false);
-
+
llvm::Value* values[2];
values[0] = new_result_global;
values[1] = new_constant_int;
-
+
ArrayRef<Value*> 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");
named_metadata->addOperand(persistent_global_md);
-
+
if (log)
log->Printf("Replacing \"%s\" with \"%s\"",
PrintValue(result_global).c_str(),
PrintValue(new_result_global).c_str());
-
- if (result_global->hasNUses(0))
+
+ if (result_global->use_empty())
{
// We need to synthesize a store for this variable, because otherwise
// there's nothing to put into its equivalent persistent variable.
-
+
BasicBlock &entry_block(llvm_function.getEntryBlock());
Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg());
-
+
if (!first_entry_instruction)
return false;
-
+
if (!result_global->hasInitializer())
{
if (log)
log->Printf("Couldn't find initializer for unused variable");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) has no writes and no initializer\n", result_name);
-
+
return false;
}
-
+
Constant *initializer = result_global->getInitializer();
-
+
StoreInst *synthesized_store = new StoreInst(initializer,
new_result_global,
first_entry_instruction);
-
+
if (log)
log->Printf("Synthesized result store \"%s\"\n", PrintValue(synthesized_store).c_str());
}
@@ -678,76 +689,51 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
{
result_global->replaceAllUsesWith(new_result_global);
}
-
+
if (!m_decl_map->AddPersistentVariable(result_decl,
- m_result_name,
+ m_result_name,
m_result_type,
true,
m_result_is_pointer))
return false;
-
+
result_global->eraseFromParent();
-
- return true;
-}
-#if 0
-static void DebugUsers(Log *log, Value *value, uint8_t depth)
-{
- if (!depth)
- return;
-
- depth--;
-
- if (log)
- log->Printf(" <Begin %d users>", value->getNumUses());
-
- for (Value::use_iterator ui = value->use_begin(), ue = value->use_end();
- ui != ue;
- ++ui)
- {
- if (log)
- log->Printf(" <Use %p> %s", *ui, PrintValue(*ui).c_str());
- DebugUsers(log, *ui, depth);
- }
-
- if (log)
- log->Printf(" <End uses>");
+ return true;
}
-#endif
bool
IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str,
llvm::GlobalVariable *cstr)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
Type *ns_str_ty = ns_str->getType();
-
+
Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext());
Type *i32_ty = Type::getInt32Ty(m_module->getContext());
Type *i8_ty = Type::getInt8Ty(m_module->getContext());
-
+
if (!m_CFStringCreateWithBytes)
{
lldb::addr_t CFStringCreateWithBytes_addr;
-
+
static lldb_private::ConstString g_CFStringCreateWithBytes_str ("CFStringCreateWithBytes");
-
+
if (!m_decl_map->GetFunctionAddress (g_CFStringCreateWithBytes_str, CFStringCreateWithBytes_addr))
{
if (log)
log->PutCString("Couldn't find CFStringCreateWithBytes in the target");
-
+
if (m_error_stream)
m_error_stream->Printf("Error [IRForTarget]: Rewriting an Objective-C constant string requires CFStringCreateWithBytes\n");
-
+
return false;
}
-
+
if (log)
log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, CFStringCreateWithBytes_addr);
-
+
// Build the function type:
//
// CFStringRef CFStringCreateWithBytes (
@@ -766,66 +752,66 @@ IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str,
// CFIndex -> long (i32 or i64, as appropriate; we ask the module for its pointer size for now)
// CFStringEncoding -> i32
// Boolean -> i8
-
+
Type *arg_type_array[5];
-
+
arg_type_array[0] = i8_ptr_ty;
arg_type_array[1] = i8_ptr_ty;
arg_type_array[2] = m_intptr_ty;
arg_type_array[3] = i32_ty;
arg_type_array[4] = i8_ty;
-
+
ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5);
-
+
llvm::Type *CFSCWB_ty = FunctionType::get(ns_str_ty, CFSCWB_arg_types, false);
-
+
// Build the constant containing the pointer to the function
PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty);
Constant *CFSCWB_addr_int = ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false);
m_CFStringCreateWithBytes = ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty);
}
-
+
ConstantDataSequential *string_array = NULL;
-
+
if (cstr)
string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer());
-
+
Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty);
Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty) : Constant::getNullValue(i8_ptr_ty);
Constant *numBytes_arg = ConstantInt::get(m_intptr_ty, cstr ? string_array->getNumElements() - 1 : 0, false);
Constant *encoding_arg = ConstantInt::get(i32_ty, 0x0600, false); /* 0x0600 is kCFStringEncodingASCII */
Constant *isExternal_arg = ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */
-
+
Value *argument_array[5];
-
+
argument_array[0] = alloc_arg;
argument_array[1] = bytes_arg;
argument_array[2] = numBytes_arg;
argument_array[3] = encoding_arg;
argument_array[4] = isExternal_arg;
-
+
ArrayRef <Value *> CFSCWB_arguments(argument_array, 5);
-
+
FunctionValueCache CFSCWB_Caller ([this, &CFSCWB_arguments] (llvm::Function *function)->llvm::Value * {
return CallInst::Create(m_CFStringCreateWithBytes,
CFSCWB_arguments,
"CFStringCreateWithBytes",
llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function)));
});
-
+
if (!UnfoldConstant(ns_str, CFSCWB_Caller, m_entry_instruction_finder))
{
if (log)
log->PutCString("Couldn't replace the NSString with the result of the call");
-
+
if (m_error_stream)
m_error_stream->Printf("Error [IRForTarget]: Couldn't replace an Objective-C constant string with a dynamic string\n");
-
+
return false;
}
-
+
ns_str->eraseFromParent();
-
+
return true;
}
@@ -833,57 +819,57 @@ bool
IRForTarget::RewriteObjCConstStrings()
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable();
-
+
for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
vi != ve;
++vi)
{
std::string value_name = vi->first().str();
const char *value_name_cstr = value_name.c_str();
-
+
if (strstr(value_name_cstr, "_unnamed_cfstring_"))
{
Value *nsstring_value = vi->second;
-
+
GlobalVariable *nsstring_global = dyn_cast<GlobalVariable>(nsstring_value);
-
+
if (!nsstring_global)
{
if (log)
log->PutCString("NSString variable is not a GlobalVariable");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a global variable\n");
-
+
return false;
}
-
+
if (!nsstring_global->hasInitializer())
{
if (log)
log->PutCString("NSString variable does not have an initializer");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have an initializer\n");
-
+
return false;
}
-
+
ConstantStruct *nsstring_struct = dyn_cast<ConstantStruct>(nsstring_global->getInitializer());
-
+
if (!nsstring_struct)
{
if (log)
log->PutCString("NSString variable's initializer is not a ConstantStruct");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a structure constant\n");
-
+
return false;
}
-
+
// We expect the following structure:
//
// struct {
@@ -892,107 +878,107 @@ IRForTarget::RewriteObjCConstStrings()
// char *str;
// long length;
// };
-
+
if (nsstring_struct->getNumOperands() != 4)
{
if (log)
log->Printf("NSString variable's initializer structure has an unexpected number of members. Should be 4, is %d", nsstring_struct->getNumOperands());
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: The struct for an Objective-C constant string is not as expected\n");
-
+
return false;
}
-
+
Constant *nsstring_member = nsstring_struct->getOperand(2);
-
+
if (!nsstring_member)
{
if (log)
log->PutCString("NSString initializer's str element was empty");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have a string initializer\n");
-
+
return false;
}
-
+
ConstantExpr *nsstring_expr = dyn_cast<ConstantExpr>(nsstring_member);
-
+
if (!nsstring_expr)
{
if (log)
log->PutCString("NSString initializer's str element is not a ConstantExpr");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not constant\n");
-
+
return false;
}
-
+
if (nsstring_expr->getOpcode() != Instruction::GetElementPtr)
{
if (log)
log->Printf("NSString initializer's str element is not a GetElementPtr expression, it's a %s", nsstring_expr->getOpcodeName());
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not an array\n");
-
+
return false;
}
-
+
Constant *nsstring_cstr = nsstring_expr->getOperand(0);
-
+
GlobalVariable *cstr_global = dyn_cast<GlobalVariable>(nsstring_cstr);
-
+
if (!cstr_global)
{
if (log)
log->PutCString("NSString initializer's str element is not a GlobalVariable");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a global\n");
-
+
return false;
}
-
+
if (!cstr_global->hasInitializer())
{
if (log)
log->PutCString("NSString initializer's str element does not have an initializer");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to initialized data\n");
-
+
return false;
}
-
+
/*
if (!cstr_array)
{
if (log)
log->PutCString("NSString initializer's str element is not a ConstantArray");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to an array\n");
-
+
return false;
}
-
+
if (!cstr_array->isCString())
{
if (log)
log->PutCString("NSString initializer's str element is not a C string array");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a C string\n");
-
+
return false;
}
*/
-
+
ConstantDataArray *cstr_array = dyn_cast<ConstantDataArray>(cstr_global->getInitializer());
-
+
if (log)
{
if (cstr_array)
@@ -1000,175 +986,175 @@ IRForTarget::RewriteObjCConstStrings()
else
log->Printf("Found NSString constant %s, which contains \"\"", value_name_cstr);
}
-
+
if (!cstr_array)
cstr_global = NULL;
-
+
if (!RewriteObjCConstString(nsstring_global, cstr_global))
- {
+ {
if (log)
log->PutCString("Error rewriting the constant string");
-
+
// We don't print an error message here because RewriteObjCConstString has done so for us.
-
+
return false;
}
}
}
-
+
for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
vi != ve;
++vi)
{
std::string value_name = vi->first().str();
const char *value_name_cstr = value_name.c_str();
-
+
if (!strcmp(value_name_cstr, "__CFConstantStringClassReference"))
{
GlobalVariable *gv = dyn_cast<GlobalVariable>(vi->second);
-
+
if (!gv)
{
if (log)
log->PutCString("__CFConstantStringClassReference is not a global variable");
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Found a CFConstantStringClassReference, but it is not a global object\n");
-
+
return false;
}
-
+
gv->eraseFromParent();
-
+
break;
}
}
-
+
return true;
}
static bool IsObjCSelectorRef (Value *value)
{
GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value);
-
+
if (!global_variable || !global_variable->hasName() || !global_variable->getName().startswith("\01L_OBJC_SELECTOR_REFERENCES_"))
return false;
-
+
return true;
}
// This function does not report errors; its callers are responsible.
-bool
+bool
IRForTarget::RewriteObjCSelector (Instruction* selector_load)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
LoadInst *load = dyn_cast<LoadInst>(selector_load);
-
+
if (!load)
return false;
-
+
// Unpack the message name from the selector. In LLVM IR, an objc_msgSend gets represented as
//
// %tmp = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_" ; <i8*>
// %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*>
//
// 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_".
// @"\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
-
+
GlobalVariable *_objc_selector_references_ = dyn_cast<GlobalVariable>(load->getPointerOperand());
-
+
if (!_objc_selector_references_ || !_objc_selector_references_->hasInitializer())
return false;
-
+
Constant *osr_initializer = _objc_selector_references_->getInitializer();
-
+
ConstantExpr *osr_initializer_expr = dyn_cast<ConstantExpr>(osr_initializer);
-
+
if (!osr_initializer_expr || osr_initializer_expr->getOpcode() != Instruction::GetElementPtr)
return false;
-
+
Value *osr_initializer_base = osr_initializer_expr->getOperand(0);
if (!osr_initializer_base)
return false;
-
+
// Find the string's initializer (a ConstantArray) and get the string from it
-
+
GlobalVariable *_objc_meth_var_name_ = dyn_cast<GlobalVariable>(osr_initializer_base);
-
+
if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer())
return false;
-
+
Constant *omvn_initializer = _objc_meth_var_name_->getInitializer();
ConstantDataArray *omvn_initializer_array = dyn_cast<ConstantDataArray>(omvn_initializer);
-
+
if (!omvn_initializer_array->isString())
return false;
-
+
std::string omvn_initializer_string = omvn_initializer_array->getAsString();
-
+
if (log)
log->Printf("Found Objective-C selector reference \"%s\"", omvn_initializer_string.c_str());
-
+
// Construct a call to sel_registerName
-
+
if (!m_sel_registerName)
{
lldb::addr_t sel_registerName_addr;
-
+
static lldb_private::ConstString g_sel_registerName_str ("sel_registerName");
if (!m_decl_map->GetFunctionAddress (g_sel_registerName_str, sel_registerName_addr))
return false;
-
+
if (log)
log->Printf("Found sel_registerName at 0x%" PRIx64, sel_registerName_addr);
-
+
// Build the function type: struct objc_selector *sel_registerName(uint8_t*)
-
+
// The below code would be "more correct," but in actuality what's required is uint8_t*
//Type *sel_type = StructType::get(m_module->getContext());
//Type *sel_ptr_type = PointerType::getUnqual(sel_type);
Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext());
-
+
Type *type_array[1];
-
+
type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext());
-
+
ArrayRef<Type *> srN_arg_types(type_array, 1);
-
+
llvm::Type *srN_type = FunctionType::get(sel_ptr_type, srN_arg_types, false);
-
+
// Build the constant containing the pointer to the function
PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type);
Constant *srN_addr_int = ConstantInt::get(m_intptr_ty, sel_registerName_addr, false);
m_sel_registerName = ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty);
}
-
+
Value *argument_array[1];
-
+
Constant *omvn_pointer = ConstantExpr::getBitCast(_objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext()));
-
+
argument_array[0] = omvn_pointer;
-
+
ArrayRef<Value *> srN_arguments(argument_array, 1);
-
- CallInst *srN_call = CallInst::Create(m_sel_registerName,
+
+ CallInst *srN_call = CallInst::Create(m_sel_registerName,
srN_arguments,
"sel_registerName",
selector_load);
-
+
// Replace the load with the call in all users
-
+
selector_load->replaceAllUsesWith(srN_call);
-
+
selector_load->eraseFromParent();
-
+
return true;
}
@@ -1178,25 +1164,25 @@ IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block)
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
BasicBlock::iterator ii;
-
+
typedef SmallVector <Instruction*, 2> InstrList;
typedef InstrList::iterator InstrIterator;
-
+
InstrList selector_loads;
-
+
for (ii = basic_block.begin();
ii != basic_block.end();
++ii)
{
Instruction &inst = *ii;
-
+
if (LoadInst *load = dyn_cast<LoadInst>(&inst))
if (IsObjCSelectorRef(load->getPointerOperand()))
selector_loads.push_back(&inst);
}
-
+
InstrIterator iter;
-
+
for (iter = selector_loads.begin();
iter != selector_loads.end();
++iter)
@@ -1205,111 +1191,111 @@ IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block)
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Couldn't change a static reference to an Objective-C selector to a dynamic reference\n");
-
+
if (log)
log->PutCString("Couldn't rewrite a reference to an Objective-C selector");
-
+
return false;
}
}
-
+
return true;
}
// This function does not report errors; its callers are responsible.
-bool
+bool
IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc);
-
+
MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr");
if (!alloc_md || !alloc_md->getNumOperands())
return false;
-
+
ConstantInt *constant_int = dyn_cast<ConstantInt>(alloc_md->getOperand(0));
-
+
if (!constant_int)
return false;
-
+
// We attempt to register this as a new persistent variable with the DeclMap.
-
+
uintptr_t ptr = constant_int->getZExtValue();
-
+
clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr);
-
+
lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(),
&decl->getASTContext());
-
+
StringRef decl_name (decl->getName());
lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size());
if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false))
return false;
-
+
GlobalVariable *persistent_global = new GlobalVariable((*m_module),
alloc->getType(),
false, /* not constant */
GlobalValue::ExternalLinkage,
NULL, /* no initializer */
alloc->getName().str().c_str());
-
+
// What we're going to do here is make believe this was a regular old external
// variable. That means we need to make the metadata valid.
-
+
NamedMDNode *named_metadata = m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs");
-
+
llvm::Value* values[2];
values[0] = persistent_global;
values[1] = constant_int;
-
+
ArrayRef<llvm::Value*> value_ref(values, 2);
MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);
named_metadata->addOperand(persistent_global_md);
-
+
// Now, since the variable is a pointer variable, we will drop in a load of that
// pointer variable.
-
+
LoadInst *persistent_load = new LoadInst (persistent_global, "", alloc);
-
+
if (log)
log->Printf("Replacing \"%s\" with \"%s\"",
PrintValue(alloc).c_str(),
PrintValue(persistent_load).c_str());
-
+
alloc->replaceAllUsesWith(persistent_load);
alloc->eraseFromParent();
-
+
return true;
}
-bool
+bool
IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block)
{
if (!m_resolve_vars)
return true;
-
+
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
BasicBlock::iterator ii;
-
+
typedef SmallVector <Instruction*, 2> InstrList;
typedef InstrList::iterator InstrIterator;
-
+
InstrList pvar_allocs;
-
+
for (ii = basic_block.begin();
ii != basic_block.end();
++ii)
{
Instruction &inst = *ii;
-
+
if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst))
{
llvm::StringRef alloc_name = alloc->getName();
-
+
if (alloc_name.startswith("$") &&
!alloc_name.startswith("$__lldb"))
{
@@ -1317,20 +1303,20 @@ IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block)
{
if (log)
log->Printf("Rejecting a numeric persistent variable.");
-
+
if (m_error_stream)
m_error_stream->Printf("Error [IRForTarget]: Names starting with $0, $1, ... are reserved for use as result names\n");
-
+
return false;
}
-
+
pvar_allocs.push_back(alloc);
}
}
}
-
+
InstrIterator iter;
-
+
for (iter = pvar_allocs.begin();
iter != pvar_allocs.end();
++iter)
@@ -1339,14 +1325,14 @@ IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block)
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite the creation of a persistent variable\n");
-
+
if (log)
log->PutCString("Couldn't rewrite the creation of a persistent variable");
-
+
return false;
}
}
-
+
return true;
}
@@ -1355,14 +1341,14 @@ IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer)
{
if (!initializer)
return true;
-
+
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log && log->GetVerbose())
log->Printf(" MaterializeInitializer(%p, %s)", data, PrintValue(initializer).c_str());
-
+
Type *initializer_type = initializer->getType();
-
+
if (ConstantInt *int_initializer = dyn_cast<ConstantInt>(initializer))
{
memcpy (data, int_initializer->getValue().getRawData(), m_target_data->getTypeStoreSize(initializer_type));
@@ -1379,17 +1365,17 @@ IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer)
{
ArrayType *array_initializer_type = array_initializer->getType();
Type *array_element_type = array_initializer_type->getElementType();
-
+
size_t element_size = m_target_data->getTypeAllocSize(array_element_type);
-
+
for (unsigned i = 0; i < array_initializer->getNumOperands(); ++i)
{
Value *operand_value = array_initializer->getOperand(i);
Constant *operand_constant = dyn_cast<Constant>(operand_value);
-
+
if (!operand_constant)
return false;
-
+
if (!MaterializeInitializer(data + (i * element_size), operand_constant))
return false;
}
@@ -1423,52 +1409,52 @@ IRForTarget::MaterializeInternalVariable (GlobalVariable *global_variable)
{
if (GlobalVariable::isExternalLinkage(global_variable->getLinkage()))
return false;
-
+
if (global_variable == m_reloc_placeholder)
return true;
-
+
uint64_t offset = m_data_allocator.GetStream().GetSize();
-
+
llvm::Type *variable_type = global_variable->getType();
-
+
Constant *initializer = global_variable->getInitializer();
-
+
llvm::Type *initializer_type = initializer->getType();
-
+
size_t size = m_target_data->getTypeAllocSize(initializer_type);
size_t align = m_target_data->getPrefTypeAlignment(initializer_type);
-
+
const size_t mask = (align - 1);
uint64_t aligned_offset = (offset + mask) & ~mask;
m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0);
offset = aligned_offset;
-
+
lldb_private::DataBufferHeap data(size, '\0');
-
+
if (initializer)
if (!MaterializeInitializer(data.GetBytes(), initializer))
return false;
-
+
m_data_allocator.GetStream().Write(data.GetBytes(), data.GetByteSize());
-
+
Constant *new_pointer = BuildRelocation(variable_type, offset);
-
+
global_variable->replaceAllUsesWith(new_pointer);
global_variable->eraseFromParent();
-
+
return true;
}
// This function does not report errors; its callers are responsible.
-bool
+bool
IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (log)
log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str());
-
+
if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr))
{
switch (constant_expr->getOpcode())
@@ -1486,31 +1472,31 @@ IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr)
{
if (!GlobalValue::isExternalLinkage(global_variable->getLinkage()))
return MaterializeInternalVariable(global_variable);
-
+
clang::NamedDecl *named_decl = DeclForGlobal(global_variable);
-
+
if (!named_decl)
{
if (IsObjCSelectorRef(llvm_value_ptr))
return true;
-
+
if (!global_variable->hasExternalLinkage())
return true;
-
+
if (log)
log->Printf("Found global variable \"%s\" without metadata", global_variable->getName().str().c_str());
-
+
return false;
}
-
+
std::string name (named_decl->getName().str());
-
+
clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl);
if (value_decl == NULL)
return false;
lldb_private::ClangASTType clang_type(&value_decl->getASTContext(), value_decl->getType());
-
+
const Type *value_type = NULL;
if (name[0] == '$')
@@ -1531,25 +1517,25 @@ IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr)
{
value_type = global_variable->getType();
}
-
+
const uint64_t value_size = clang_type.GetByteSize();
- off_t value_alignment = (clang_type.GetTypeBitAlign() + 7ull) / 8ull;
-
+ lldb::offset_t value_alignment = (clang_type.GetTypeBitAlign() + 7ull) / 8ull;
+
if (log)
{
- log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRId64 "]",
- name.c_str(),
+ log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRIu64 "]",
+ name.c_str(),
clang_type.GetQualType().getAsString().c_str(),
PrintType(value_type).c_str(),
- value_size,
+ value_size,
value_alignment);
}
-
-
+
+
if (named_decl && !m_decl_map->AddValueToStruct(named_decl,
lldb_private::ConstString (name.c_str()),
llvm_value_ptr,
- value_size,
+ value_size,
value_alignment))
{
if (!global_variable->hasExternalLinkage())
@@ -1564,45 +1550,45 @@ IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr)
{
if (log)
log->Printf("Function pointers aren't handled right now");
-
+
return false;
}
-
+
return true;
}
// This function does not report errors; its callers are responsible.
bool
IRForTarget::HandleSymbol (Value *symbol)
-{
+{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
lldb_private::ConstString name(symbol->getName().str().c_str());
-
+
lldb::addr_t symbol_addr = m_decl_map->GetSymbolAddress (name, lldb::eSymbolTypeAny);
-
+
if (symbol_addr == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf ("Symbol \"%s\" had no address", name.GetCString());
-
+
return false;
}
if (log)
log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr);
-
+
Type *symbol_type = symbol->getType();
-
+
Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false);
-
+
Value *symbol_addr_ptr = ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type);
-
+
if (log)
log->Printf("Replacing %s with %s", PrintValue(symbol).c_str(), PrintValue(symbol_addr_ptr).c_str());
-
+
symbol->replaceAllUsesWith(symbol_addr_ptr);
-
+
return true;
}
@@ -1610,10 +1596,10 @@ bool
IRForTarget::MaybeHandleCallArguments (CallInst *Old)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (log)
log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str());
-
+
for (unsigned op_index = 0, num_ops = Old->getNumArgOperands();
op_index < num_ops;
++op_index)
@@ -1621,10 +1607,10 @@ IRForTarget::MaybeHandleCallArguments (CallInst *Old)
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite one of the arguments of a function call.\n");
-
+
return false;
}
-
+
return true;
}
@@ -1634,55 +1620,53 @@ IRForTarget::HandleObjCClass(Value *classlist_reference)
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
GlobalVariable *global_variable = dyn_cast<GlobalVariable>(classlist_reference);
-
+
if (!global_variable)
return false;
-
+
Constant *initializer = global_variable->getInitializer();
-
+
if (!initializer)
return false;
-
+
if (!initializer->hasName())
return false;
-
+
StringRef name(initializer->getName());
lldb_private::ConstString name_cstr(name.str().c_str());
lldb::addr_t class_ptr = m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass);
-
+
if (log)
log->Printf("Found reference to Objective-C class %s (0x%llx)", name_cstr.AsCString(), (unsigned long long)class_ptr);
-
+
if (class_ptr == LLDB_INVALID_ADDRESS)
return false;
-
- if (global_variable->use_begin() == global_variable->use_end())
+
+ if (global_variable->use_empty())
return false;
-
+
SmallVector<LoadInst *, 2> load_instructions;
-
- for (Value::use_iterator i = global_variable->use_begin(), e = global_variable->use_end();
- i != e;
- ++i)
+
+ for (llvm::User *u : global_variable->users())
{
- if (LoadInst *load_instruction = dyn_cast<LoadInst>(*i))
+ if (LoadInst *load_instruction = dyn_cast<LoadInst>(u))
load_instructions.push_back(load_instruction);
}
-
+
if (load_instructions.empty())
return false;
-
+
Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr);
-
+
for (LoadInst *load_instruction : load_instructions)
{
Constant *class_bitcast = ConstantExpr::getIntToPtr(class_addr, load_instruction->getType());
-
+
load_instruction->replaceAllUsesWith(class_bitcast);
-
+
load_instruction->eraseFromParent();
}
-
+
return true;
}
@@ -1690,54 +1674,54 @@ bool
IRForTarget::RemoveCXAAtExit (BasicBlock &basic_block)
{
BasicBlock::iterator ii;
-
+
std::vector<CallInst *> calls_to_remove;
-
+
for (ii = basic_block.begin();
ii != basic_block.end();
++ii)
{
Instruction &inst = *ii;
-
+
CallInst *call = dyn_cast<CallInst>(&inst);
-
+
// MaybeHandleCallArguments handles error reporting; we are silent here
if (!call)
continue;
-
+
bool remove = false;
-
+
llvm::Function *func = call->getCalledFunction();
-
+
if (func && func->getName() == "__cxa_atexit")
remove = true;
-
+
llvm::Value *val = call->getCalledValue();
-
+
if (val && val->getName() == "__cxa_atexit")
remove = true;
-
+
if (remove)
calls_to_remove.push_back(call);
}
-
+
for (std::vector<CallInst *>::iterator ci = calls_to_remove.begin(), ce = calls_to_remove.end();
ci != ce;
++ci)
{
(*ci)->eraseFromParent();
}
-
+
return true;
}
bool
IRForTarget::ResolveCalls(BasicBlock &basic_block)
-{
+{
/////////////////////////////////////////////////////////////////////////
// Prepare the current basic block for execution in the remote process
//
-
+
BasicBlock::iterator ii;
for (ii = basic_block.begin();
@@ -1745,14 +1729,14 @@ IRForTarget::ResolveCalls(BasicBlock &basic_block)
++ii)
{
Instruction &inst = *ii;
-
+
CallInst *call = dyn_cast<CallInst>(&inst);
-
+
// MaybeHandleCallArguments handles error reporting; we are silent here
if (call && !MaybeHandleCallArguments(call))
return false;
}
-
+
return true;
}
@@ -1760,68 +1744,58 @@ bool
IRForTarget::ResolveExternals (Function &llvm_function)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- for (Module::global_iterator global = m_module->global_begin(), end = m_module->global_end();
- global != end;
- ++global)
+
+ for (GlobalVariable &global_var : m_module->globals())
{
- if (!global)
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: global variable is NULL");
-
- return false;
- }
-
- std::string global_name = (*global).getName().str();
-
+ std::string global_name = global_var.getName().str();
+
if (log)
- log->Printf("Examining %s, DeclForGlobalValue returns %p",
+ log->Printf("Examining %s, DeclForGlobalValue returns %p",
global_name.c_str(),
- DeclForGlobal(global));
-
+ static_cast<void*>(DeclForGlobal(&global_var)));
+
if (global_name.find("OBJC_IVAR") == 0)
{
- if (!HandleSymbol(global))
+ if (!HandleSymbol(&global_var))
{
if (m_error_stream)
m_error_stream->Printf("Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol %s\n", global_name.c_str());
-
+
return false;
}
}
else if (global_name.find("OBJC_CLASSLIST_REFERENCES_$") != global_name.npos)
{
- if (!HandleObjCClass(global))
+ if (!HandleObjCClass(&global_var))
{
if (m_error_stream)
m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n");
-
+
return false;
}
}
else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != global_name.npos)
{
- if (!HandleObjCClass(global))
+ if (!HandleObjCClass(&global_var))
{
if (m_error_stream)
m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n");
-
+
return false;
}
}
- else if (DeclForGlobal(global))
+ else if (DeclForGlobal(&global_var))
{
- if (!MaybeHandleVariable (global))
+ if (!MaybeHandleVariable (&global_var))
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite external variable %s\n", global_name.c_str());
-
+
return false;
}
}
}
-
+
return true;
}
@@ -1829,40 +1803,36 @@ bool
IRForTarget::ReplaceStrings ()
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
typedef std::map <GlobalVariable *, size_t> OffsetsTy;
-
+
OffsetsTy offsets;
-
- for (Module::global_iterator gi = m_module->global_begin(), ge = m_module->global_end();
- gi != ge;
- ++gi)
- {
- GlobalVariable *gv = gi;
-
- if (!gv->hasInitializer())
+
+ for (GlobalVariable &gv : m_module->globals())
+ {
+ if (!gv.hasInitializer())
continue;
-
- Constant *gc = gv->getInitializer();
-
+
+ Constant *gc = gv.getInitializer();
+
std::string str;
-
+
if (gc->isNullValue())
{
Type *gc_type = gc->getType();
-
+
ArrayType *gc_array_type = dyn_cast<ArrayType>(gc_type);
-
+
if (!gc_array_type)
continue;
-
+
Type *gc_element_type = gc_array_type->getElementType();
-
+
IntegerType *gc_integer_type = dyn_cast<IntegerType>(gc_element_type);
-
+
if (gc_integer_type->getBitWidth() != 8)
continue;
-
+
str = "";
}
else
@@ -1871,108 +1841,102 @@ IRForTarget::ReplaceStrings ()
if (!gc_array)
continue;
-
+
if (!gc_array->isCString())
continue;
-
+
if (log)
log->Printf("Found a GlobalVariable with string initializer %s", PrintValue(gc).c_str());
-
+
str = gc_array->getAsString();
}
-
- offsets[gv] = m_data_allocator.GetStream().GetSize();
-
+
+ offsets[&gv] = m_data_allocator.GetStream().GetSize();
+
m_data_allocator.GetStream().Write(str.c_str(), str.length() + 1);
}
-
+
Type *char_ptr_ty = Type::getInt8PtrTy(m_module->getContext());
-
+
for (OffsetsTy::iterator oi = offsets.begin(), oe = offsets.end();
oi != oe;
++oi)
{
GlobalVariable *gv = oi->first;
size_t offset = oi->second;
-
+
Constant *new_initializer = BuildRelocation(char_ptr_ty, offset);
-
+
if (log)
log->Printf("Replacing GV %s with %s", PrintValue(gv).c_str(), PrintValue(new_initializer).c_str());
-
- for (GlobalVariable::use_iterator ui = gv->use_begin(), ue = gv->use_end();
- ui != ue;
- ++ui)
+
+ for (llvm::User *u : gv->users())
{
if (log)
- log->Printf("Found use %s", PrintValue(*ui).c_str());
-
- ConstantExpr *const_expr = dyn_cast<ConstantExpr>(*ui);
- StoreInst *store_inst = dyn_cast<StoreInst>(*ui);
-
+ log->Printf("Found use %s", PrintValue(u).c_str());
+
+ ConstantExpr *const_expr = dyn_cast<ConstantExpr>(u);
+ StoreInst *store_inst = dyn_cast<StoreInst>(u);
+
if (const_expr)
{
if (const_expr->getOpcode() != Instruction::GetElementPtr)
{
if (log)
log->Printf("Use (%s) of string variable is not a GetElementPtr constant", PrintValue(const_expr).c_str());
-
+
return false;
}
-
+
Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, const_expr->getOperand(0)->getType());
Constant *new_gep = const_expr->getWithOperandReplaced(0, bit_cast);
-
+
const_expr->replaceAllUsesWith(new_gep);
}
else if (store_inst)
{
Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, store_inst->getValueOperand()->getType());
-
+
store_inst->setOperand(0, bit_cast);
}
else
{
if (log)
log->Printf("Use (%s) of string variable is neither a constant nor a store", PrintValue(const_expr).c_str());
-
+
return false;
}
}
-
+
gv->eraseFromParent();
}
-
+
return true;
}
-bool
+bool
IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
typedef SmallVector <Value*, 2> ConstantList;
typedef SmallVector <llvm::Instruction*, 2> UserList;
typedef ConstantList::iterator ConstantIterator;
typedef UserList::iterator UserIterator;
-
+
ConstantList static_constants;
UserList static_users;
-
+
for (BasicBlock::iterator ii = basic_block.begin(), ie = basic_block.end();
ii != ie;
++ii)
{
llvm::Instruction &inst = *ii;
-
- for (Instruction::op_iterator oi = inst.op_begin(), oe = inst.op_end();
- oi != oe;
- ++oi)
+
+ for (Value *operand_val : inst.operand_values())
{
- Value *operand_val = oi->get();
-
ConstantFP *operand_constant_fp = dyn_cast<ConstantFP>(operand_val);
-
+
if (operand_constant_fp/* && operand_constant_fp->getType()->isX86_FP80Ty()*/)
{
static_constants.push_back(operand_val);
@@ -1980,10 +1944,10 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
}
}
}
-
+
ConstantIterator constant_iter;
UserIterator user_iter;
-
+
for (constant_iter = static_constants.begin(), user_iter = static_users.begin();
constant_iter != static_constants.end();
++constant_iter, ++user_iter)
@@ -1992,17 +1956,17 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
llvm::Instruction *inst = *user_iter;
ConstantFP *operand_constant_fp = dyn_cast<ConstantFP>(operand_val);
-
+
if (operand_constant_fp)
{
Type *operand_type = operand_constant_fp->getType();
APFloat operand_apfloat = operand_constant_fp->getValueAPF();
APInt operand_apint = operand_apfloat.bitcastToAPInt();
-
+
const uint8_t* operand_raw_data = (const uint8_t*)operand_apint.getRawData();
size_t operand_data_size = operand_apint.getBitWidth() / 8;
-
+
if (log)
{
std::string s;
@@ -2015,16 +1979,16 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
ss << " ";
}
ss.flush();
-
- log->Printf("Found ConstantFP with size %zu and raw data %s", operand_data_size, s.c_str());
+
+ log->Printf("Found ConstantFP with size %" PRIu64 " and raw data %s", (uint64_t)operand_data_size, s.c_str());
}
-
+
lldb_private::DataBufferHeap data(operand_data_size, 0);
-
+
if (lldb::endian::InlHostByteOrder() != m_data_allocator.GetStream().GetByteOrder())
{
uint8_t *data_bytes = data.GetBytes();
-
+
for (size_t index = 0;
index < operand_data_size;
++index)
@@ -2036,77 +2000,72 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
{
memcpy(data.GetBytes(), operand_raw_data, operand_data_size);
}
-
+
uint64_t offset = m_data_allocator.GetStream().GetSize();
-
+
size_t align = m_target_data->getPrefTypeAlignment(operand_type);
-
+
const size_t mask = (align - 1);
uint64_t aligned_offset = (offset + mask) & ~mask;
m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0);
- offset = aligned_offset;
-
+
m_data_allocator.GetStream().Write(data.GetBytes(), operand_data_size);
-
+
llvm::Type *fp_ptr_ty = operand_constant_fp->getType()->getPointerTo();
-
+
Constant *new_pointer = BuildRelocation(fp_ptr_ty, aligned_offset);
-
+
llvm::LoadInst *fp_load = new llvm::LoadInst(new_pointer, "fp_load", inst);
-
+
operand_constant_fp->replaceAllUsesWith(fp_load);
}
}
-
+
return true;
}
static bool isGuardVariableRef(Value *V)
{
Constant *Old = NULL;
-
+
if (!(Old = dyn_cast<Constant>(V)))
return false;
-
+
ConstantExpr *CE = NULL;
-
+
if ((CE = dyn_cast<ConstantExpr>(V)))
{
if (CE->getOpcode() != Instruction::BitCast)
return false;
-
+
Old = CE->getOperand(0);
}
-
+
GlobalVariable *GV = dyn_cast<GlobalVariable>(Old);
-
+
if (!GV || !GV->hasName() || !GV->getName().startswith("_ZGV"))
return false;
-
+
return true;
}
-void
+void
IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction* guard_load)
{
Constant* zero(ConstantInt::get(Type::getInt8Ty(m_module->getContext()), 0, true));
- Value::use_iterator ui;
-
- for (ui = guard_load->use_begin();
- ui != guard_load->use_end();
- ++ui)
+ for (llvm::User *u : guard_load->users())
{
- if (isa<Constant>(*ui))
+ if (isa<Constant>(u))
{
// do nothing for the moment
}
else
{
- ui->replaceUsesOfWith(guard_load, zero);
+ u->replaceUsesOfWith(guard_load, zero);
}
}
-
+
guard_load->eraseFromParent();
}
@@ -2117,46 +2076,46 @@ static void ExciseGuardStore(Instruction* guard_store)
bool
IRForTarget::RemoveGuards(BasicBlock &basic_block)
-{
+{
///////////////////////////////////////////////////////
// Eliminate any reference to guard variables found.
//
-
+
BasicBlock::iterator ii;
-
+
typedef SmallVector <Instruction*, 2> InstrList;
typedef InstrList::iterator InstrIterator;
-
+
InstrList guard_loads;
InstrList guard_stores;
-
+
for (ii = basic_block.begin();
ii != basic_block.end();
++ii)
{
Instruction &inst = *ii;
-
+
if (LoadInst *load = dyn_cast<LoadInst>(&inst))
if (isGuardVariableRef(load->getPointerOperand()))
- guard_loads.push_back(&inst);
-
- if (StoreInst *store = dyn_cast<StoreInst>(&inst))
+ guard_loads.push_back(&inst);
+
+ if (StoreInst *store = dyn_cast<StoreInst>(&inst))
if (isGuardVariableRef(store->getPointerOperand()))
guard_stores.push_back(&inst);
}
-
+
InstrIterator iter;
-
+
for (iter = guard_loads.begin();
iter != guard_loads.end();
++iter)
TurnGuardLoadIntoZero(*iter);
-
+
for (iter = guard_stores.begin();
iter != guard_stores.end();
++iter)
ExciseGuardStore(*iter);
-
+
return true;
}
@@ -2168,27 +2127,23 @@ IRForTarget::UnfoldConstant(Constant *old_constant,
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- Value::use_iterator ui;
-
SmallVector<User*, 16> users;
-
+
// We do this because the use list might change, invalidating our iterator.
// Much better to keep a work list ourselves.
- for (ui = old_constant->use_begin();
- ui != old_constant->use_end();
- ++ui)
- users.push_back(*ui);
-
+ for (llvm::User *u : old_constant->users())
+ users.push_back(u);
+
for (size_t i = 0;
i < users.size();
++i)
{
User *user = users[i];
-
+
if (Constant *constant = dyn_cast<Constant>(user))
{
// synthesize a new non-constant equivalent of the constant
-
+
if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant))
{
switch (constant_expr->getOpcode())
@@ -2198,20 +2153,20 @@ IRForTarget::UnfoldConstant(Constant *old_constant,
log->Printf("Unhandled constant expression type: \"%s\"", PrintValue(constant_expr).c_str());
return false;
case Instruction::BitCast:
- {
+ {
FunctionValueCache bit_cast_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* {
// UnaryExpr
// OperandList[0] is value
if (constant_expr->getOperand(0) != old_constant)
return constant_expr;
-
+
return new BitCastInst(value_maker.GetValue(function),
constant_expr->getType(),
"",
llvm::cast<Instruction>(entry_instruction_finder.GetValue(function)));
});
-
+
if (!UnfoldConstant(constant_expr, bit_cast_maker, entry_instruction_finder))
return false;
}
@@ -2221,35 +2176,35 @@ IRForTarget::UnfoldConstant(Constant *old_constant,
// GetElementPtrConstantExpr
// OperandList[0] is base
// OperandList[1]... are indices
-
+
FunctionValueCache get_element_pointer_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* {
Value *ptr = constant_expr->getOperand(0);
-
+
if (ptr == old_constant)
ptr = value_maker.GetValue(function);
-
+
std::vector<Value*> index_vector;
-
+
unsigned operand_index;
unsigned num_operands = constant_expr->getNumOperands();
-
+
for (operand_index = 1;
operand_index < num_operands;
++operand_index)
{
Value *operand = constant_expr->getOperand(operand_index);
-
+
if (operand == old_constant)
operand = value_maker.GetValue(function);
-
+
index_vector.push_back(operand);
}
-
+
ArrayRef <Value*> indices(index_vector);
-
+
return GetElementPtrInst::Create(ptr, indices, "", llvm::cast<Instruction>(entry_instruction_finder.GetValue(function)));
});
-
+
if (!UnfoldConstant(constant_expr, get_element_pointer_maker, entry_instruction_finder))
return false;
}
@@ -2277,162 +2232,162 @@ IRForTarget::UnfoldConstant(Constant *old_constant,
}
}
}
-
+
if (!isa<GlobalValue>(old_constant))
{
old_constant->destroyConstant();
}
-
+
return true;
}
-bool
+bool
IRForTarget::ReplaceVariables (Function &llvm_function)
{
if (!m_resolve_vars)
return true;
-
+
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
m_decl_map->DoStructLayout();
-
+
if (log)
log->Printf("Element arrangement:");
-
+
uint32_t num_elements;
uint32_t element_index;
-
+
size_t size;
- off_t alignment;
-
+ lldb::offset_t alignment;
+
if (!m_decl_map->GetStructInfo (num_elements, size, alignment))
return false;
-
+
Function::arg_iterator iter(llvm_function.getArgumentList().begin());
-
+
if (iter == llvm_function.getArgumentList().end())
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes no arguments (should take at least a struct pointer)");
-
+
return false;
}
-
+
Argument *argument = iter;
-
+
if (argument->getName().equals("this"))
{
++iter;
-
+
if (iter == llvm_function.getArgumentList().end())
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'this' argument (should take a struct pointer too)");
-
+
return false;
}
-
+
argument = iter;
}
else if (argument->getName().equals("self"))
{
++iter;
-
+
if (iter == llvm_function.getArgumentList().end())
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' argument (should take '_cmd' and a struct pointer too)");
-
+
return false;
}
-
+
if (!iter->getName().equals("_cmd"))
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes '%s' after 'self' argument (should take '_cmd')", iter->getName().str().c_str());
-
+
return false;
}
-
+
++iter;
-
+
if (iter == llvm_function.getArgumentList().end())
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' and '_cmd' arguments (should take a struct pointer too)");
-
+
return false;
}
-
+
argument = iter;
}
-
+
if (!argument->getName().equals("$__lldb_arg"))
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes an argument named '%s' instead of the struct pointer", argument->getName().str().c_str());
-
+
return false;
}
-
+
if (log)
log->Printf("Arg: \"%s\"", PrintValue(argument).c_str());
-
+
BasicBlock &entry_block(llvm_function.getEntryBlock());
Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg());
-
+
if (!FirstEntryInstruction)
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find the first instruction in the wrapper for use in rewriting");
-
+
return false;
}
-
+
LLVMContext &context(m_module->getContext());
IntegerType *offset_type(Type::getInt32Ty(context));
-
+
if (!offset_type)
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Couldn't produce an offset type");
-
+
return false;
}
-
+
for (element_index = 0; element_index < num_elements; ++element_index)
{
const clang::NamedDecl *decl = NULL;
Value *value = NULL;
- off_t offset;
+ lldb::offset_t offset;
lldb_private::ConstString name;
-
+
if (!m_decl_map->GetStructElement (decl, value, offset, name, element_index))
{
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Structure information is incomplete");
-
+
return false;
}
-
+
if (log)
- log->Printf(" \"%s\" (\"%s\") placed at %" PRId64,
+ log->Printf(" \"%s\" (\"%s\") placed at %" PRIu64,
name.GetCString(),
decl->getNameAsString().c_str(),
offset);
-
+
if (value)
{
if (log)
log->Printf(" Replacing [%s]", PrintValue(value).c_str());
-
+
FunctionValueCache body_result_maker ([this, name, offset_type, offset, argument, value] (llvm::Function *function)->llvm::Value * {
// Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result
// variable is an rvalue, we have to synthesize a dereference of the appropriate structure
// entry in order to produce the static variable that the AST thinks it is accessing.
-
+
llvm::Instruction *entry_instruction = llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function));
-
+
ConstantInt *offset_int(ConstantInt::get(offset_type, offset, true));
GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(argument,
offset_int,
@@ -2445,19 +2400,19 @@ IRForTarget::ReplaceVariables (Function &llvm_function)
value->getType()->getPointerTo(),
"",
entry_instruction);
-
+
LoadInst *load = new LoadInst(bit_cast, "", entry_instruction);
-
+
return load;
}
else
{
BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", entry_instruction);
-
+
return bit_cast;
}
- });
-
+ });
+
if (Constant *constant = dyn_cast<Constant>(value))
{
UnfoldConstant(constant, body_result_maker, m_entry_instruction_finder);
@@ -2472,15 +2427,15 @@ IRForTarget::ReplaceVariables (Function &llvm_function)
log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(value).c_str());
return false;
}
-
+
if (GlobalVariable *var = dyn_cast<GlobalVariable>(value))
var->eraseFromParent();
}
}
-
+
if (log)
- log->Printf("Total structure [align %" PRId64 ", size %zu]", alignment, size);
-
+ log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", (int64_t)alignment, (uint64_t)size);
+
return true;
}
@@ -2488,29 +2443,29 @@ llvm::Constant *
IRForTarget::BuildRelocation(llvm::Type *type, uint64_t offset)
{
llvm::Constant *offset_int = ConstantInt::get(m_intptr_ty, offset);
-
+
llvm::Constant *offset_array[1];
-
+
offset_array[0] = offset_int;
-
+
llvm::ArrayRef<llvm::Constant *> offsets(offset_array, 1);
-
+
llvm::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr(m_reloc_placeholder, offsets);
llvm::Constant *reloc_getbitcast = ConstantExpr::getBitCast(reloc_getelementptr, type);
-
+
return reloc_getbitcast;
}
-bool
+bool
IRForTarget::CompleteDataAllocation ()
-{
+{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (!m_data_allocator.GetStream().GetSize())
return true;
-
+
lldb::addr_t allocation = m_data_allocator.Allocate();
-
+
if (log)
{
if (allocation)
@@ -2518,15 +2473,15 @@ IRForTarget::CompleteDataAllocation ()
else
log->Printf("Failed to allocate static data");
}
-
+
if (!allocation || allocation == LLDB_INVALID_ADDRESS)
return false;
-
+
Constant *relocated_addr = ConstantInt::get(m_intptr_ty, (uint64_t)allocation);
Constant *relocated_bitcast = ConstantExpr::getIntToPtr(relocated_addr, llvm::Type::getInt8PtrTy(m_module->getContext()));
-
+
m_reloc_placeholder->replaceAllUsesWith(relocated_bitcast);
-
+
m_reloc_placeholder->eraseFromParent();
return true;
@@ -2538,47 +2493,39 @@ IRForTarget::StripAllGVs (Module &llvm_module)
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
std::vector<GlobalVariable *> global_vars;
std::set<GlobalVariable *>erased_vars;
-
+
bool erased = true;
-
+
while (erased)
{
erased = false;
-
- for (Module::global_iterator gi = llvm_module.global_begin(), ge = llvm_module.global_end();
- gi != ge;
- ++gi)
+
+ for (GlobalVariable &global_var : llvm_module.globals())
{
- GlobalVariable *global_var = dyn_cast<GlobalVariable>(gi);
-
- global_var->removeDeadConstantUsers();
-
- if (global_var->use_empty())
+ global_var.removeDeadConstantUsers();
+
+ if (global_var.use_empty())
{
if (log)
log->Printf("Did remove %s",
- PrintValue(global_var).c_str());
- global_var->eraseFromParent();
+ PrintValue(&global_var).c_str());
+ global_var.eraseFromParent();
erased = true;
break;
}
}
}
-
- for (Module::global_iterator gi = llvm_module.global_begin(), ge = llvm_module.global_end();
- gi != ge;
- ++gi)
+
+ for (GlobalVariable &global_var : llvm_module.globals())
{
- GlobalVariable *global_var = dyn_cast<GlobalVariable>(gi);
+ GlobalValue::user_iterator ui = global_var.user_begin();
- GlobalValue::use_iterator ui = global_var->use_begin();
-
if (log)
log->Printf("Couldn't remove %s because of %s",
- PrintValue(global_var).c_str(),
+ PrintValue(&global_var).c_str(),
PrintValue(*ui).c_str());
}
-
+
return true;
}
@@ -2586,46 +2533,46 @@ bool
IRForTarget::runOnModule (Module &llvm_module)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
m_module = &llvm_module;
m_target_data.reset(new DataLayout(m_module));
m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(), m_target_data->getPointerSizeInBits());
-
+
if (log)
{
std::string s;
raw_string_ostream oss(s);
-
+
m_module->print(oss, NULL);
-
+
oss.flush();
-
+
log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str());
}
-
+
Function* main_function = m_module->getFunction(StringRef(m_func_name.c_str()));
-
+
if (!main_function)
{
if (log)
log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str());
-
+
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", m_func_name.c_str());
return false;
}
-
+
if (!FixFunctionLinkage (*main_function))
{
if (log)
log->Printf("Couldn't fix the linkage for the function");
-
+
return false;
}
-
+
llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext());
-
+
m_reloc_placeholder = new llvm::GlobalVariable((*m_module),
int8_ty,
false /* IsConstant */,
@@ -2639,14 +2586,14 @@ IRForTarget::runOnModule (Module &llvm_module)
////////////////////////////////////////////////////////////
// Replace $__lldb_expr_result with a persistent variable
//
-
+
if (!CreateResultVariable(*main_function))
{
if (log)
log->Printf("CreateResultVariable() failed");
-
+
// CreateResultVariable() reports its own errors, so we don't do so here
-
+
return false;
}
@@ -2654,25 +2601,25 @@ IRForTarget::runOnModule (Module &llvm_module)
{
std::string s;
raw_string_ostream oss(s);
-
+
m_module->print(oss, NULL);
-
+
oss.flush();
-
+
log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str());
}
-
+
for (Module::iterator fi = m_module->begin(), fe = m_module->end();
fi != fe;
++fi)
{
llvm::Function *function = fi;
-
+
if (function->begin() == function->end())
continue;
-
+
Function::iterator bbi;
-
+
for (bbi = function->begin();
bbi != function->end();
++bbi)
@@ -2681,62 +2628,62 @@ IRForTarget::runOnModule (Module &llvm_module)
{
if (log)
log->Printf("RemoveGuards() failed");
-
+
// RemoveGuards() reports its own errors, so we don't do so here
-
+
return false;
}
-
+
if (!RewritePersistentAllocs(*bbi))
{
if (log)
log->Printf("RewritePersistentAllocs() failed");
-
+
// RewritePersistentAllocs() reports its own errors, so we don't do so here
-
+
return false;
}
-
+
if (!RemoveCXAAtExit(*bbi))
{
if (log)
log->Printf("RemoveCXAAtExit() failed");
-
+
// RemoveCXAAtExit() reports its own errors, so we don't do so here
-
+
return false;
}
}
}
-
+
///////////////////////////////////////////////////////////////////////////////
// Fix all Objective-C constant strings to use NSStringWithCString:encoding:
//
-
+
if (!RewriteObjCConstStrings())
{
if (log)
log->Printf("RewriteObjCConstStrings() failed");
-
+
// RewriteObjCConstStrings() reports its own errors, so we don't do so here
-
+
return false;
}
-
+
///////////////////////////////
// Resolve function pointers
//
-
+
if (!ResolveFunctionPointers(llvm_module))
{
if (log)
log->Printf("ResolveFunctionPointers() failed");
-
+
// ResolveFunctionPointers() reports its own errors, so we don't do so here
-
+
return false;
}
-
+
for (Module::iterator fi = m_module->begin(), fe = m_module->end();
fi != fe;
++fi)
@@ -2751,9 +2698,9 @@ IRForTarget::runOnModule (Module &llvm_module)
{
if (log)
log->Printf("RewriteObjCSelectors() failed");
-
+
// RewriteObjCSelectors() reports its own errors, so we don't do so here
-
+
return false;
}
}
@@ -2764,7 +2711,7 @@ IRForTarget::runOnModule (Module &llvm_module)
++fi)
{
llvm::Function *function = fi;
-
+
for (llvm::Function::iterator bbi = function->begin(), bbe = function->end();
bbi != bbe;
++bbi)
@@ -2773,81 +2720,81 @@ IRForTarget::runOnModule (Module &llvm_module)
{
if (log)
log->Printf("ResolveCalls() failed");
-
+
// ResolveCalls() reports its own errors, so we don't do so here
-
+
return false;
}
-
+
if (!ReplaceStaticLiterals(*bbi))
{
if (log)
log->Printf("ReplaceStaticLiterals() failed");
-
+
return false;
}
}
}
-
+
////////////////////////////////////////////////////////////////////////
// Run function-level passes that only make sense on the main function
//
-
+
if (!ResolveExternals(*main_function))
{
if (log)
log->Printf("ResolveExternals() failed");
-
+
// ResolveExternals() reports its own errors, so we don't do so here
-
+
return false;
}
-
+
if (!ReplaceVariables(*main_function))
{
if (log)
log->Printf("ReplaceVariables() failed");
-
+
// ReplaceVariables() reports its own errors, so we don't do so here
-
+
return false;
}
-
+
if (!ReplaceStrings())
{
if (log)
log->Printf("ReplaceStrings() failed");
-
+
return false;
}
-
+
if (!CompleteDataAllocation())
{
if (log)
log->Printf("CompleteDataAllocation() failed");
-
+
return false;
}
-
+
if (!StripAllGVs(llvm_module))
{
if (log)
log->Printf("StripAllGVs() failed");
}
-
+
if (log && log->GetVerbose())
{
std::string s;
raw_string_ostream oss(s);
-
+
m_module->print(oss, NULL);
-
+
oss.flush();
-
+
log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str());
}
-
- return true;
+
+ return true;
}
void
diff --git a/source/Expression/IRInterpreter.cpp b/source/Expression/IRInterpreter.cpp
index 71ef8d6457bc..d11bdc1671b6 100644
--- a/source/Expression/IRInterpreter.cpp
+++ b/source/Expression/IRInterpreter.cpp
@@ -20,6 +20,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
@@ -27,7 +28,7 @@
using namespace llvm;
-static std::string
+static std::string
PrintValue(const Value *value, bool truncate = false)
{
std::string s;
@@ -36,13 +37,13 @@ PrintValue(const Value *value, bool truncate = false)
rso.flush();
if (truncate)
s.resize(s.length() - 1);
-
+
size_t offset;
while ((offset = s.find('\n')) != s.npos)
s.erase(offset, 1);
while (s[0] == ' ' || s[0] == '\t')
s.erase(0, 1);
-
+
return s;
}
@@ -58,25 +59,48 @@ PrintType(const Type *type, bool truncate = false)
return s;
}
+static bool
+CanIgnoreCall (const CallInst *call)
+{
+ const llvm::Function *called_function = call->getCalledFunction();
+
+ if (!called_function)
+ return false;
+
+ if (called_function->isIntrinsic())
+ {
+ switch (called_function->getIntrinsicID())
+ {
+ default:
+ break;
+ case llvm::Intrinsic::dbg_declare:
+ case llvm::Intrinsic::dbg_value:
+ return true;
+ }
+ }
+
+ return false;
+}
+
class InterpreterStackFrame
{
public:
typedef std::map <const Value*, lldb::addr_t> ValueMap;
-
+
ValueMap m_values;
DataLayout &m_target_data;
lldb_private::IRMemoryMap &m_memory_map;
const BasicBlock *m_bb;
BasicBlock::const_iterator m_ii;
BasicBlock::const_iterator m_ie;
-
+
lldb::addr_t m_frame_process_address;
size_t m_frame_size;
lldb::addr_t m_stack_pointer;
-
+
lldb::ByteOrder m_byte_order;
size_t m_addr_byte_size;
-
+
InterpreterStackFrame (DataLayout &target_data,
lldb_private::IRMemoryMap &memory_map,
lldb::addr_t stack_frame_bottom,
@@ -86,41 +110,41 @@ public:
{
m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig);
m_addr_byte_size = (target_data.getPointerSize(0));
-
+
m_frame_process_address = stack_frame_bottom;
m_frame_size = stack_frame_top - stack_frame_bottom;
m_stack_pointer = stack_frame_top;
}
-
+
~InterpreterStackFrame ()
{
}
-
+
void Jump (const BasicBlock *bb)
{
m_bb = bb;
m_ii = m_bb->begin();
m_ie = m_bb->end();
}
-
+
std::string SummarizeValue (const Value *value)
{
lldb_private::StreamString ss;
ss.Printf("%s", PrintValue(value).c_str());
-
+
ValueMap::iterator i = m_values.find(value);
if (i != m_values.end())
{
lldb::addr_t addr = i->second;
-
+
ss.Printf(" 0x%llx", (unsigned long long)addr);
}
-
+
return ss.GetString();
}
-
+
bool AssignToMatchType (lldb_private::Scalar &scalar, uint64_t u64value, Type *type)
{
size_t type_size = m_target_data.getTypeStoreSize(type);
@@ -142,36 +166,36 @@ public:
default:
return false;
}
-
+
return true;
}
-
+
bool EvaluateValue (lldb_private::Scalar &scalar, const Value *value, Module &module)
{
const Constant *constant = dyn_cast<Constant>(value);
-
+
if (constant)
{
APInt value_apint;
-
+
if (!ResolveConstantValue(value_apint, constant))
return false;
-
+
return AssignToMatchType(scalar, value_apint.getLimitedValue(), value->getType());
}
else
{
lldb::addr_t process_address = ResolveValue(value, module);
size_t value_size = m_target_data.getTypeStoreSize(value->getType());
-
+
lldb_private::DataExtractor value_extractor;
lldb_private::Error extract_error;
-
+
m_memory_map.GetMemoryData(value_extractor, process_address, value_size, extract_error);
-
+
if (!extract_error.Success())
return false;
-
+
lldb::offset_t offset = 0;
if (value_size == 1 || value_size == 2 || value_size == 4 || value_size == 8)
{
@@ -179,38 +203,38 @@ public:
return AssignToMatchType(scalar, u64value, value->getType());
}
}
-
+
return false;
}
-
+
bool AssignValue (const Value *value, lldb_private::Scalar &scalar, Module &module)
{
lldb::addr_t process_address = ResolveValue (value, module);
-
+
if (process_address == LLDB_INVALID_ADDRESS)
return false;
-
+
lldb_private::Scalar cast_scalar;
-
+
if (!AssignToMatchType(cast_scalar, scalar.GetRawBits64(0), value->getType()))
return false;
-
+
size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType());
-
+
lldb_private::DataBufferHeap buf(value_byte_size, 0);
-
+
lldb_private::Error get_data_error;
-
+
if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(), m_byte_order, get_data_error))
return false;
-
+
lldb_private::Error write_error;
-
+
m_memory_map.WriteMemory(process_address, buf.GetBytes(), buf.GetByteSize(), write_error);
-
+
return write_error.Success();
}
-
+
bool ResolveConstantValue (APInt &value, const Constant *constant)
{
switch (constant->getValueID())
@@ -246,27 +270,27 @@ public:
{
ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
ConstantExpr::const_op_iterator op_end = constant_expr->op_end();
-
+
Constant *base = dyn_cast<Constant>(*op_cursor);
-
+
if (!base)
return false;
-
+
if (!ResolveConstantValue(value, base))
return false;
-
+
op_cursor++;
-
+
if (op_cursor == op_end)
return true; // no offset to apply!
-
+
SmallVector <Value *, 8> indices (op_cursor, op_end);
-
+
uint64_t offset = m_target_data.getIndexedOffset(base->getType(), indices);
-
+
const bool is_signed = true;
value += APInt(value.getBitWidth(), offset, is_signed);
-
+
return true;
}
}
@@ -282,27 +306,27 @@ public:
}
return false;
}
-
+
bool MakeArgument(const Argument *value, uint64_t address)
{
lldb::addr_t data_address = Malloc(value->getType());
-
+
if (data_address == LLDB_INVALID_ADDRESS)
return false;
-
+
lldb_private::Error write_error;
-
+
m_memory_map.WritePointerToMemory(data_address, address, write_error);
-
+
if (!write_error.Success())
{
lldb_private::Error free_error;
m_memory_map.Free(data_address, free_error);
return false;
}
-
+
m_values[value] = data_address;
-
+
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
@@ -311,75 +335,75 @@ public:
log->Printf(" Data region : %llx", (unsigned long long)address);
log->Printf(" Ref region : %llx", (unsigned long long)data_address);
}
-
+
return true;
}
-
+
bool ResolveConstant (lldb::addr_t process_address, const Constant *constant)
{
APInt resolved_value;
-
+
if (!ResolveConstantValue(resolved_value, constant))
return false;
-
+
lldb_private::StreamString buffer (lldb_private::Stream::eBinary,
m_memory_map.GetAddressByteSize(),
m_memory_map.GetByteOrder());
-
+
size_t constant_size = m_target_data.getTypeStoreSize(constant->getType());
-
+
const uint64_t *raw_data = resolved_value.getRawData();
-
+
buffer.PutRawBytes(raw_data, constant_size, lldb::endian::InlHostByteOrder());
-
+
lldb_private::Error write_error;
-
+
m_memory_map.WriteMemory(process_address, (const uint8_t*)buffer.GetData(), constant_size, write_error);
-
+
return write_error.Success();
}
-
+
lldb::addr_t Malloc (size_t size, uint8_t byte_alignment)
{
lldb::addr_t ret = m_stack_pointer;
-
+
ret -= size;
ret -= (ret % byte_alignment);
-
+
if (ret < m_frame_process_address)
return LLDB_INVALID_ADDRESS;
-
+
m_stack_pointer = ret;
return ret;
}
-
+
lldb::addr_t MallocPointer ()
{
return Malloc(m_target_data.getPointerSize(), m_target_data.getPointerPrefAlignment());
}
-
+
lldb::addr_t Malloc (llvm::Type *type)
{
lldb_private::Error alloc_error;
-
+
return Malloc(m_target_data.getTypeAllocSize(type), m_target_data.getPrefTypeAlignment(type));
}
-
+
std::string PrintData (lldb::addr_t addr, llvm::Type *type)
{
size_t length = m_target_data.getTypeStoreSize(type);
-
+
lldb_private::DataBufferHeap buf(length, 0);
-
+
lldb_private::Error read_error;
-
+
m_memory_map.ReadMemory(buf.GetBytes(), addr, length, read_error);
-
+
if (!read_error.Success())
return std::string("<couldn't read data>");
-
+
lldb_private::StreamString ss;
-
+
for (size_t i = 0; i < length; i++)
{
if ((!(i & 0xf)) && i)
@@ -387,21 +411,21 @@ public:
else
ss.Printf("%02hhx ", buf.GetBytes()[i]);
}
-
+
return ss.GetString();
}
-
+
lldb::addr_t ResolveValue (const Value *value, Module &module)
{
ValueMap::iterator i = m_values.find(value);
-
+
if (i != m_values.end())
return i->second;
-
+
// Fall back and allocate space [allocation type Alloca]
-
+
lldb::addr_t data_address = Malloc(value->getType());
-
+
if (const Constant *constant = dyn_cast<Constant>(value))
{
if (!ResolveConstant (data_address, constant))
@@ -411,7 +435,7 @@ public:
return LLDB_INVALID_ADDRESS;
}
}
-
+
m_values[value] = data_address;
return data_address;
}
@@ -434,9 +458,9 @@ IRInterpreter::CanInterpret (llvm::Module &module,
lldb_private::Error &error)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
bool saw_function_with_body = false;
-
+
for (Module::iterator fi = module.begin(), fe = module.end();
fi != fe;
++fi)
@@ -448,7 +472,7 @@ IRInterpreter::CanInterpret (llvm::Module &module,
saw_function_with_body = true;
}
}
-
+
for (Function::iterator bbi = function.begin(), bbe = function.end();
bbi != bbe;
++bbi)
@@ -471,26 +495,48 @@ IRInterpreter::CanInterpret (llvm::Module &module,
case Instruction::Alloca:
case Instruction::BitCast:
case Instruction::Br:
+ break;
+ case Instruction::Call:
+ {
+ CallInst *call_inst = dyn_cast<CallInst>(ii);
+
+ if (!call_inst)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ if (!CanIgnoreCall(call_inst))
+ {
+ if (log)
+ log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(unsupported_opcode_error);
+ return false;
+ }
+ }
+ break;
case Instruction::GetElementPtr:
break;
case Instruction::ICmp:
{
ICmpInst *icmp_inst = dyn_cast<ICmpInst>(ii);
-
+
if (!icmp_inst)
{
error.SetErrorToGenericError();
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
switch (icmp_inst->getPredicate())
{
default:
{
if (log)
log->Printf("Unsupported ICmp predicate: %s", PrintValue(ii).c_str());
-
+
error.SetErrorToGenericError();
error.SetErrorString(unsupported_opcode_error);
return false;
@@ -531,14 +577,14 @@ IRInterpreter::CanInterpret (llvm::Module &module,
case Instruction::ZExt:
break;
}
-
+
for (int oi = 0, oe = ii->getNumOperands();
oi != oe;
++oi)
{
Value *operand = ii->getOperand(oi);
Type *operand_type = operand->getType();
-
+
switch (operand_type->getTypeID())
{
default:
@@ -553,9 +599,9 @@ IRInterpreter::CanInterpret (llvm::Module &module,
}
}
}
-
+
}
-
+
return true;}
bool
@@ -568,60 +614,83 @@ IRInterpreter::Interpret (llvm::Module &module,
lldb::addr_t stack_frame_top)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (log)
{
std::string s;
raw_string_ostream oss(s);
-
+
module.print(oss, NULL);
-
+
oss.flush();
-
+
log->Printf("Module as passed in to IRInterpreter::Interpret: \n\"%s\"", s.c_str());
}
-
+
DataLayout data_layout(&module);
-
+
InterpreterStackFrame frame(data_layout, memory_map, stack_frame_bottom, stack_frame_top);
-
+
if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS)
{
error.SetErrorString("Couldn't allocate stack frame");
}
-
+
int arg_index = 0;
-
+
for (llvm::Function::arg_iterator ai = function.arg_begin(), ae = function.arg_end();
ai != ae;
++ai, ++arg_index)
{
- if (args.size() < arg_index)
+ if (args.size() < static_cast<size_t>(arg_index))
{
error.SetErrorString ("Not enough arguments passed in to function");
return false;
}
-
+
lldb::addr_t ptr = args[arg_index];
frame.MakeArgument(ai, ptr);
}
-
+
uint32_t num_insts = 0;
-
+
frame.Jump(function.begin());
-
+
while (frame.m_ii != frame.m_ie && (++num_insts < 4096))
{
const Instruction *inst = frame.m_ii;
-
+
if (log)
log->Printf("Interpreting %s", PrintValue(inst).c_str());
-
+
switch (inst->getOpcode())
{
default:
break;
+ case Instruction::Call:
+ {
+ const CallInst *call_inst = dyn_cast<CallInst>(inst);
+
+ if (!call_inst)
+ {
+ if (log)
+ log->Printf("getOpcode() returns %s, but instruction is not a CallInst", inst->getOpcodeName());
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ if (!CanIgnoreCall(call_inst))
+ {
+ if (log)
+ log->Printf("The interpreter shouldn't have accepted %s", PrintValue(call_inst).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+ }
+ break;
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
@@ -637,7 +706,7 @@ IRInterpreter::Interpret (llvm::Module &module,
case Instruction::Xor:
{
const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst);
-
+
if (!bin_op)
{
if (log)
@@ -646,13 +715,13 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
Value *lhs = inst->getOperand(0);
Value *rhs = inst->getOperand(1);
-
+
lldb_private::Scalar L;
lldb_private::Scalar R;
-
+
if (!frame.EvaluateValue(L, lhs, module))
{
if (log)
@@ -661,7 +730,7 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
if (!frame.EvaluateValue(R, rhs, module))
{
if (log)
@@ -670,9 +739,9 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
lldb_private::Scalar result;
-
+
switch (inst->getOpcode())
{
default:
@@ -722,9 +791,9 @@ IRInterpreter::Interpret (llvm::Module &module,
result = L ^ R;
break;
}
-
+
frame.AssignValue(inst, result, module);
-
+
if (log)
{
log->Printf("Interpreted a %s", inst->getOpcodeName());
@@ -737,7 +806,7 @@ IRInterpreter::Interpret (llvm::Module &module,
case Instruction::Alloca:
{
const AllocaInst *alloca_inst = dyn_cast<AllocaInst>(inst);
-
+
if (!alloca_inst)
{
if (log)
@@ -746,7 +815,7 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
if (alloca_inst->isArrayAllocation())
{
if (log)
@@ -755,17 +824,17 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(unsupported_opcode_error);
return false;
}
-
+
// The semantics of Alloca are:
// Create a region R of virtual memory of type T, backed by a data buffer
// Create a region P of virtual memory of type T*, backed by a data buffer
// Write the virtual address of R into P
-
+
Type *T = alloca_inst->getAllocatedType();
Type *Tptr = alloca_inst->getType();
-
+
lldb::addr_t R = frame.Malloc(T);
-
+
if (R == LLDB_INVALID_ADDRESS)
{
if (log)
@@ -774,9 +843,9 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(memory_allocation_error);
return false;
}
-
+
lldb::addr_t P = frame.Malloc(Tptr);
-
+
if (P == LLDB_INVALID_ADDRESS)
{
if (log)
@@ -785,11 +854,11 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(memory_allocation_error);
return false;
}
-
+
lldb_private::Error write_error;
-
+
memory_map.WritePointerToMemory(P, R, write_error);
-
+
if (!write_error.Success())
{
if (log)
@@ -801,9 +870,9 @@ IRInterpreter::Interpret (llvm::Module &module,
memory_map.Free(R, free_error);
return false;
}
-
+
frame.m_values[alloca_inst] = P;
-
+
if (log)
{
log->Printf("Interpreted an AllocaInst");
@@ -816,7 +885,7 @@ IRInterpreter::Interpret (llvm::Module &module,
case Instruction::ZExt:
{
const CastInst *cast_inst = dyn_cast<CastInst>(inst);
-
+
if (!cast_inst)
{
if (log)
@@ -825,11 +894,11 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
Value *source = cast_inst->getOperand(0);
-
+
lldb_private::Scalar S;
-
+
if (!frame.EvaluateValue(S, source, module))
{
if (log)
@@ -838,14 +907,14 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
frame.AssignValue(inst, S, module);
}
break;
case Instruction::SExt:
{
const CastInst *cast_inst = dyn_cast<CastInst>(inst);
-
+
if (!cast_inst)
{
if (log)
@@ -854,11 +923,11 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
Value *source = cast_inst->getOperand(0);
-
+
lldb_private::Scalar S;
-
+
if (!frame.EvaluateValue(S, source, module))
{
if (log)
@@ -867,18 +936,18 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
S.MakeSigned();
-
+
lldb_private::Scalar S_signextend(S.SLongLong());
-
+
frame.AssignValue(inst, S_signextend, module);
}
break;
case Instruction::Br:
{
const BranchInst *br_inst = dyn_cast<BranchInst>(inst);
-
+
if (!br_inst)
{
if (log)
@@ -887,13 +956,13 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
if (br_inst->isConditional())
{
Value *condition = br_inst->getCondition();
-
+
lldb_private::Scalar C;
-
+
if (!frame.EvaluateValue(C, condition, module))
{
if (log)
@@ -902,12 +971,12 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
if (C.GetRawBits64(0))
frame.Jump(br_inst->getSuccessor(0));
else
frame.Jump(br_inst->getSuccessor(1));
-
+
if (log)
{
log->Printf("Interpreted a BrInst with a condition");
@@ -917,7 +986,7 @@ IRInterpreter::Interpret (llvm::Module &module,
else
{
frame.Jump(br_inst->getSuccessor(0));
-
+
if (log)
{
log->Printf("Interpreted a BrInst with no condition");
@@ -928,7 +997,7 @@ IRInterpreter::Interpret (llvm::Module &module,
case Instruction::GetElementPtr:
{
const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst);
-
+
if (!gep_inst)
{
if (log)
@@ -937,12 +1006,12 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
const Value *pointer_operand = gep_inst->getPointerOperand();
Type *pointer_type = pointer_operand->getType();
-
+
lldb_private::Scalar P;
-
+
if (!frame.EvaluateValue(P, pointer_operand, module))
{
if (log)
@@ -951,25 +1020,25 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
typedef SmallVector <Value *, 8> IndexVector;
typedef IndexVector::iterator IndexIterator;
-
+
SmallVector <Value *, 8> indices (gep_inst->idx_begin(),
gep_inst->idx_end());
-
+
SmallVector <Value *, 8> const_indices;
-
+
for (IndexIterator ii = indices.begin(), ie = indices.end();
ii != ie;
++ii)
{
ConstantInt *constant_index = dyn_cast<ConstantInt>(*ii);
-
+
if (!constant_index)
{
lldb_private::Scalar I;
-
+
if (!frame.EvaluateValue(I, *ii, module))
{
if (log)
@@ -978,22 +1047,22 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
if (log)
log->Printf("Evaluated constant index %s as %llu", PrintValue(*ii).c_str(), I.ULongLong(LLDB_INVALID_ADDRESS));
-
+
constant_index = cast<ConstantInt>(ConstantInt::get((*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS)));
}
-
+
const_indices.push_back(constant_index);
}
-
+
uint64_t offset = data_layout.getIndexedOffset(pointer_type, const_indices);
-
+
lldb_private::Scalar Poffset = P + offset;
-
+
frame.AssignValue(inst, Poffset, module);
-
+
if (log)
{
log->Printf("Interpreted a GetElementPtrInst");
@@ -1005,7 +1074,7 @@ IRInterpreter::Interpret (llvm::Module &module,
case Instruction::ICmp:
{
const ICmpInst *icmp_inst = dyn_cast<ICmpInst>(inst);
-
+
if (!icmp_inst)
{
if (log)
@@ -1014,15 +1083,15 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
CmpInst::Predicate predicate = icmp_inst->getPredicate();
-
+
Value *lhs = inst->getOperand(0);
Value *rhs = inst->getOperand(1);
-
+
lldb_private::Scalar L;
lldb_private::Scalar R;
-
+
if (!frame.EvaluateValue(L, lhs, module))
{
if (log)
@@ -1031,7 +1100,7 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
if (!frame.EvaluateValue(R, rhs, module))
{
if (log)
@@ -1040,9 +1109,9 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
lldb_private::Scalar result;
-
+
switch (predicate)
{
default:
@@ -1086,9 +1155,9 @@ IRInterpreter::Interpret (llvm::Module &module,
result = (L <= R);
break;
}
-
+
frame.AssignValue(inst, result, module);
-
+
if (log)
{
log->Printf("Interpreted an ICmpInst");
@@ -1101,7 +1170,7 @@ IRInterpreter::Interpret (llvm::Module &module,
case Instruction::IntToPtr:
{
const IntToPtrInst *int_to_ptr_inst = dyn_cast<IntToPtrInst>(inst);
-
+
if (!int_to_ptr_inst)
{
if (log)
@@ -1110,11 +1179,11 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
Value *src_operand = int_to_ptr_inst->getOperand(0);
-
+
lldb_private::Scalar I;
-
+
if (!frame.EvaluateValue(I, src_operand, module))
{
if (log)
@@ -1123,9 +1192,9 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
frame.AssignValue(inst, I, module);
-
+
if (log)
{
log->Printf("Interpreted an IntToPtr");
@@ -1137,7 +1206,7 @@ IRInterpreter::Interpret (llvm::Module &module,
case Instruction::PtrToInt:
{
const PtrToIntInst *ptr_to_int_inst = dyn_cast<PtrToIntInst>(inst);
-
+
if (!ptr_to_int_inst)
{
if (log)
@@ -1146,11 +1215,11 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
Value *src_operand = ptr_to_int_inst->getOperand(0);
-
+
lldb_private::Scalar I;
-
+
if (!frame.EvaluateValue(I, src_operand, module))
{
if (log)
@@ -1159,9 +1228,9 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
frame.AssignValue(inst, I, module);
-
+
if (log)
{
log->Printf("Interpreted a PtrToInt");
@@ -1173,7 +1242,7 @@ IRInterpreter::Interpret (llvm::Module &module,
case Instruction::Trunc:
{
const TruncInst *trunc_inst = dyn_cast<TruncInst>(inst);
-
+
if (!trunc_inst)
{
if (log)
@@ -1182,11 +1251,11 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
Value *src_operand = trunc_inst->getOperand(0);
-
+
lldb_private::Scalar I;
-
+
if (!frame.EvaluateValue(I, src_operand, module))
{
if (log)
@@ -1195,9 +1264,9 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
frame.AssignValue(inst, I, module);
-
+
if (log)
{
log->Printf("Interpreted a Trunc");
@@ -1209,7 +1278,7 @@ IRInterpreter::Interpret (llvm::Module &module,
case Instruction::Load:
{
const LoadInst *load_inst = dyn_cast<LoadInst>(inst);
-
+
if (!load_inst)
{
if (log)
@@ -1218,15 +1287,15 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
// The semantics of Load are:
// Create a region D that will contain the loaded data
// Resolve the region P containing a pointer
// Dereference P to get the region R that the data should be loaded from
// Transfer a unit of type type(D) from R to D
-
+
const Value *pointer_operand = load_inst->getPointerOperand();
-
+
Type *pointer_ty = pointer_operand->getType();
PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
if (!pointer_ptr_ty)
@@ -1238,10 +1307,10 @@ IRInterpreter::Interpret (llvm::Module &module,
return false;
}
Type *target_ty = pointer_ptr_ty->getElementType();
-
+
lldb::addr_t D = frame.ResolveValue(load_inst, module);
lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
-
+
if (D == LLDB_INVALID_ADDRESS)
{
if (log)
@@ -1250,7 +1319,7 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
if (P == LLDB_INVALID_ADDRESS)
{
if (log)
@@ -1259,11 +1328,11 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
lldb::addr_t R;
lldb_private::Error read_error;
memory_map.ReadPointerFromMemory(&R, P, read_error);
-
+
if (!read_error.Success())
{
if (log)
@@ -1272,10 +1341,10 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(memory_read_error);
return false;
}
-
+
size_t target_size = data_layout.getTypeStoreSize(target_ty);
lldb_private::DataBufferHeap buffer(target_size, 0);
-
+
read_error.Clear();
memory_map.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(), read_error);
if (!read_error.Success())
@@ -1286,7 +1355,7 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(memory_read_error);
return false;
}
-
+
lldb_private::Error write_error;
memory_map.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(), write_error);
if (!write_error.Success())
@@ -1297,7 +1366,7 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(memory_read_error);
return false;
}
-
+
if (log)
{
log->Printf("Interpreted a LoadInst");
@@ -1314,7 +1383,7 @@ IRInterpreter::Interpret (llvm::Module &module,
case Instruction::Store:
{
const StoreInst *store_inst = dyn_cast<StoreInst>(inst);
-
+
if (!store_inst)
{
if (log)
@@ -1323,25 +1392,25 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
// The semantics of Store are:
// Resolve the region D containing the data to be stored
// Resolve the region P containing a pointer
// Dereference P to get the region R that the data should be stored in
// Transfer a unit of type type(D) from D to R
-
+
const Value *value_operand = store_inst->getValueOperand();
const Value *pointer_operand = store_inst->getPointerOperand();
-
+
Type *pointer_ty = pointer_operand->getType();
PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
if (!pointer_ptr_ty)
return false;
Type *target_ty = pointer_ptr_ty->getElementType();
-
+
lldb::addr_t D = frame.ResolveValue(value_operand, module);
lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
-
+
if (D == LLDB_INVALID_ADDRESS)
{
if (log)
@@ -1350,7 +1419,7 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
if (P == LLDB_INVALID_ADDRESS)
{
if (log)
@@ -1359,11 +1428,11 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(bad_value_error);
return false;
}
-
+
lldb::addr_t R;
lldb_private::Error read_error;
memory_map.ReadPointerFromMemory(&R, P, read_error);
-
+
if (!read_error.Success())
{
if (log)
@@ -1372,10 +1441,10 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(memory_read_error);
return false;
}
-
+
size_t target_size = data_layout.getTypeStoreSize(target_ty);
lldb_private::DataBufferHeap buffer(target_size, 0);
-
+
read_error.Clear();
memory_map.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(), read_error);
if (!read_error.Success())
@@ -1386,7 +1455,7 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(memory_read_error);
return false;
}
-
+
lldb_private::Error write_error;
memory_map.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(), write_error);
if (!write_error.Success())
@@ -1397,7 +1466,7 @@ IRInterpreter::Interpret (llvm::Module &module,
error.SetErrorString(memory_write_error);
return false;
}
-
+
if (log)
{
log->Printf("Interpreted a StoreInst");
@@ -1408,16 +1477,16 @@ IRInterpreter::Interpret (llvm::Module &module,
}
break;
}
-
+
++frame.m_ii;
}
-
+
if (num_insts >= 4096)
{
error.SetErrorToGenericError();
error.SetErrorString(infinite_loop_error);
return false;
}
-
+
return false;
}
diff --git a/source/Expression/IRMemoryMap.cpp b/source/Expression/IRMemoryMap.cpp
index 53f74aebfed1..a4fe7a968379 100644
--- a/source/Expression/IRMemoryMap.cpp
+++ b/source/Expression/IRMemoryMap.cpp
@@ -28,11 +28,11 @@ IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
IRMemoryMap::~IRMemoryMap ()
{
lldb::ProcessSP process_sp = m_process_wp.lock();
-
+
if (process_sp)
{
AllocationMap::iterator iter;
-
+
Error err;
while ((iter = m_allocations.begin()) != m_allocations.end())
@@ -51,54 +51,32 @@ IRMemoryMap::FindSpace (size_t size)
{
lldb::TargetSP target_sp = m_target_wp.lock();
lldb::ProcessSP process_sp = m_process_wp.lock();
-
+
lldb::addr_t ret = LLDB_INVALID_ADDRESS;
-
+ if (size == 0)
+ return ret;
+
if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
{
Error alloc_error;
-
+
ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
-
+
if (!alloc_error.Success())
return LLDB_INVALID_ADDRESS;
else
return ret;
}
-
- for (int iterations = 0; iterations < 16; ++iterations)
+
+ ret = 0;
+ if (!m_allocations.empty())
{
- lldb::addr_t candidate = LLDB_INVALID_ADDRESS;
-
- switch (target_sp->GetArchitecture().GetAddressByteSize())
- {
- case 4:
- {
- uint32_t random_data = rand();
- candidate = random_data;
- candidate &= ~0xfffull;
- break;
- }
- case 8:
- {
- uint32_t random_low = rand();
- uint32_t random_high = rand();
- candidate = random_high;
- candidate <<= 32ull;
- candidate |= random_low;
- candidate &= ~0xfffull;
- break;
- }
- }
-
- if (IntersectsAllocation(candidate, size))
- continue;
-
- ret = candidate;
-
- return ret;
+ auto back = m_allocations.rbegin();
+ lldb::addr_t addr = back->first;
+ size_t alloc_size = back->second.m_size;
+ ret = llvm::RoundUpToAlignment(addr+alloc_size, 4096);
}
-
+
return ret;
}
@@ -107,9 +85,9 @@ IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
{
if (addr == LLDB_INVALID_ADDRESS)
return m_allocations.end();
-
+
AllocationMap::iterator iter = m_allocations.lower_bound (addr);
-
+
if (iter == m_allocations.end() ||
iter->first > addr)
{
@@ -117,54 +95,69 @@ IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
return m_allocations.end();
iter--;
}
-
+
if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
return iter;
-
+
return m_allocations.end();
}
bool
-IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size)
+IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) const
{
if (addr == LLDB_INVALID_ADDRESS)
return false;
-
- AllocationMap::iterator iter = m_allocations.lower_bound (addr);
-
- if (iter == m_allocations.end() ||
- iter->first > addr)
- {
- if (iter == m_allocations.begin())
- return false;
-
- iter--;
+
+ AllocationMap::const_iterator iter = m_allocations.lower_bound (addr);
+
+ // Since we only know that the returned interval begins at a location greater than or
+ // equal to where the given interval begins, it's possible that the given interval
+ // intersects either the returned interval or the previous interval. Thus, we need to
+ // check both. Note that we only need to check these two intervals. Since all intervals
+ // are disjoint it is not possible that an adjacent interval does not intersect, but a
+ // non-adjacent interval does intersect.
+ if (iter != m_allocations.end()) {
+ if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
+ return true;
}
-
- while (iter != m_allocations.end() && iter->second.m_process_alloc < addr + size)
- {
- if (iter->second.m_process_start + iter->second.m_size > addr)
+
+ if (iter != m_allocations.begin()) {
+ --iter;
+ if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
return true;
-
- ++iter;
}
-
+
return false;
}
+bool
+IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2) {
+ // Given two half open intervals [A, B) and [X, Y), the only 6 permutations that satisfy
+ // A<B and X<Y are the following:
+ // A B X Y
+ // A X B Y (intersects)
+ // A X Y B (intersects)
+ // X A B Y (intersects)
+ // X A Y B (intersects)
+ // X Y A B
+ // The first is B <= X, and the last is Y <= A.
+ // So the condition is !(B <= X || Y <= A)), or (X < B && A < Y)
+ return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
+}
+
lldb::ByteOrder
IRMemoryMap::GetByteOrder()
{
lldb::ProcessSP process_sp = m_process_wp.lock();
-
+
if (process_sp)
return process_sp->GetByteOrder();
-
+
lldb::TargetSP target_sp = m_target_wp.lock();
-
+
if (target_sp)
return target_sp->GetArchitecture().GetByteOrder();
-
+
return lldb::eByteOrderInvalid;
}
@@ -172,31 +165,31 @@ uint32_t
IRMemoryMap::GetAddressByteSize()
{
lldb::ProcessSP process_sp = m_process_wp.lock();
-
+
if (process_sp)
return process_sp->GetAddressByteSize();
-
+
lldb::TargetSP target_sp = m_target_wp.lock();
-
+
if (target_sp)
return target_sp->GetArchitecture().GetAddressByteSize();
-
+
return UINT32_MAX;
}
ExecutionContextScope *
-IRMemoryMap::GetBestExecutionContextScope()
+IRMemoryMap::GetBestExecutionContextScope() const
{
lldb::ProcessSP process_sp = m_process_wp.lock();
-
+
if (process_sp)
return process_sp.get();
-
+
lldb::TargetSP target_sp = m_target_wp.lock();
-
+
if (target_sp)
return target_sp.get();
-
+
return NULL;
}
@@ -234,8 +227,9 @@ IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
lldb::addr_t
IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
{
+ lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
error.Clear();
-
+
lldb::ProcessSP process_sp;
lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
@@ -247,7 +241,7 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
allocation_size = alignment;
else
allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size;
-
+
switch (policy)
{
default:
@@ -265,6 +259,8 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
break;
case eAllocationPolicyMirror:
process_sp = m_process_wp.lock();
+ if (log)
+ log->Printf ("IRMemoryMap::%s process_sp=0x%" PRIx64 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", __FUNCTION__, (lldb::addr_t) process_sp.get (), process_sp && process_sp->CanJIT () ? "true" : "false", process_sp && process_sp->IsAlive () ? "true" : "false");
if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
{
allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
@@ -273,6 +269,8 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
}
else
{
+ if (log)
+ log->Printf ("IRMemoryMap::%s switching to eAllocationPolicyHostOnly due to failed condition (see previous expr log message)", __FUNCTION__);
policy = eAllocationPolicyHostOnly;
allocation_address = FindSpace(allocation_size);
if (allocation_address == LLDB_INVALID_ADDRESS)
@@ -308,8 +306,8 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
}
break;
}
-
-
+
+
lldb::addr_t mask = alignment - 1;
aligned_address = (allocation_address + mask) & (~mask);
@@ -319,11 +317,11 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
permissions,
alignment,
policy);
-
- if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+
+ if (log)
{
const char * policy_string;
-
+
switch (policy)
{
default:
@@ -339,7 +337,7 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
policy_string = "eAllocationPolicyMirror";
break;
}
-
+
log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
(uint64_t)allocation_size,
(uint64_t)alignment,
@@ -347,7 +345,7 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
policy_string,
aligned_address);
}
-
+
return aligned_address;
}
@@ -355,16 +353,16 @@ void
IRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
{
error.Clear();
-
+
AllocationMap::iterator iter = m_allocations.find(process_address);
-
+
if (iter == m_allocations.end())
{
error.SetErrorToGenericError();
error.SetErrorString("Couldn't leak: allocation doesn't exist");
return;
}
-
+
Allocation &allocation = iter->second;
allocation.m_leak = true;
@@ -374,18 +372,18 @@ void
IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
{
error.Clear();
-
+
AllocationMap::iterator iter = m_allocations.find(process_address);
-
+
if (iter == m_allocations.end())
{
error.SetErrorToGenericError();
error.SetErrorString("Couldn't free: allocation doesn't exist");
return;
}
-
+
Allocation &allocation = iter->second;
-
+
switch (allocation.m_policy)
{
default:
@@ -397,7 +395,7 @@ IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
if (process_sp->CanJIT() && process_sp->IsAlive())
process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
}
-
+
break;
}
case eAllocationPolicyMirror:
@@ -408,15 +406,15 @@ IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
process_sp->DeallocateMemory(allocation.m_process_alloc);
}
}
-
+
if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
- {
+ {
log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
(uint64_t)process_address,
iter->second.m_process_start,
iter->second.m_process_start + iter->second.m_size);
}
-
+
m_allocations.erase(iter);
}
@@ -424,28 +422,28 @@ void
IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
{
error.Clear();
-
+
AllocationMap::iterator iter = FindAllocation(process_address, size);
-
+
if (iter == m_allocations.end())
{
lldb::ProcessSP process_sp = m_process_wp.lock();
-
+
if (process_sp)
{
process_sp->WriteMemory(process_address, bytes, size, error);
return;
}
-
+
error.SetErrorToGenericError();
error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
return;
}
-
+
Allocation &allocation = iter->second;
-
+
uint64_t offset = process_address - allocation.m_process_start;
-
+
lldb::ProcessSP process_sp;
switch (allocation.m_policy)
@@ -489,9 +487,9 @@ IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, si
}
break;
}
-
+
if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
- {
+ {
log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
(uint64_t)process_address,
(uint64_t)bytes,
@@ -505,10 +503,10 @@ void
IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
{
error.Clear();
-
+
if (size == UINT32_MAX)
size = scalar.GetByteSize();
-
+
if (size > 0)
{
uint8_t buf[32];
@@ -535,9 +533,9 @@ void
IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
{
error.Clear();
-
+
Scalar scalar(address);
-
+
WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
}
@@ -545,39 +543,46 @@ void
IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
{
error.Clear();
-
+
AllocationMap::iterator iter = FindAllocation(process_address, size);
-
+
if (iter == m_allocations.end())
{
lldb::ProcessSP process_sp = m_process_wp.lock();
-
+
if (process_sp)
{
process_sp->ReadMemory(process_address, bytes, size, error);
return;
}
-
+
lldb::TargetSP target_sp = m_target_wp.lock();
-
+
if (target_sp)
{
Address absolute_address(process_address);
target_sp->ReadMemory(absolute_address, false, bytes, size, error);
return;
}
-
+
error.SetErrorToGenericError();
error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist");
return;
}
-
+
Allocation &allocation = iter->second;
-
+
uint64_t offset = process_address - allocation.m_process_start;
-
+
+ if (offset > allocation.m_size)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read: data is not in the allocation");
+ return;
+ }
+
lldb::ProcessSP process_sp;
-
+
switch (allocation.m_policy)
{
default:
@@ -591,6 +596,13 @@ IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t si
error.SetErrorString("Couldn't read: data buffer is empty");
return;
}
+ if (allocation.m_data.GetByteSize() < offset + size)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read: not enough underlying data");
+ return;
+ }
+
::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
break;
case eAllocationPolicyMirror:
@@ -622,7 +634,7 @@ IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t si
}
break;
}
-
+
if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
{
log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
@@ -638,19 +650,19 @@ void
IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
{
error.Clear();
-
+
if (size > 0)
{
DataBufferHeap buf(size, 0);
ReadMemory(buf.GetBytes(), process_address, size, error);
-
+
if (!error.Success())
return;
-
+
DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
-
+
lldb::offset_t offset = 0;
-
+
switch (size)
{
default:
@@ -675,15 +687,15 @@ void
IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
{
error.Clear();
-
+
Scalar pointer_scalar;
ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
-
+
if (!error.Success())
return;
-
+
*address = pointer_scalar.ULongLong();
-
+
return;
}
@@ -691,20 +703,20 @@ void
IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
{
error.Clear();
-
+
if (size > 0)
{
AllocationMap::iterator iter = FindAllocation(process_address, size);
-
+
if (iter == m_allocations.end())
{
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
return;
}
-
+
Allocation &allocation = iter->second;
-
+
switch (allocation.m_policy)
{
default:
@@ -754,5 +766,3 @@ IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_addre
return;
}
}
-
-
diff --git a/source/Expression/Materializer.cpp b/source/Expression/Materializer.cpp
index 90687c0739d9..b11921635e5a 100644
--- a/source/Expression/Materializer.cpp
+++ b/source/Expression/Materializer.cpp
@@ -95,7 +95,7 @@ public:
}
if (log)
- log->Printf("Allocated %s (0x%" PRIx64 ") sucessfully", m_persistent_variable_sp->GetName().GetCString(), mem);
+ log->Printf("Allocated %s (0x%" PRIx64 ") successfully", m_persistent_variable_sp->GetName().GetCString(), mem);
// Put the location of the spare memory into the live data of the ValueObject.
@@ -443,10 +443,26 @@ public:
return;
}
+ Error valobj_error = valobj_sp->GetError();
+
+ if (valobj_error.Fail())
+ {
+ err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s", m_variable_sp->GetName().AsCString(), valobj_error.AsCString());
+ return;
+ }
+
if (m_is_reference)
{
DataExtractor valobj_extractor;
- valobj_sp->GetData(valobj_extractor);
+ Error extract_error;
+ valobj_sp->GetData(valobj_extractor, extract_error);
+
+ if (!extract_error.Success())
+ {
+ err.SetErrorStringWithFormat("couldn't read contents of reference variable %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString());
+ return;
+ }
+
lldb::offset_t offset = 0;
lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);
@@ -478,8 +494,14 @@ public:
else
{
DataExtractor data;
- valobj_sp->GetData(data);
-
+ Error extract_error;
+ valobj_sp->GetData(data, extract_error);
+ if (!extract_error.Success())
+ {
+ err.SetErrorStringWithFormat("couldn't get the value of %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString());
+ return;
+ }
+
if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
{
err.SetErrorStringWithFormat("trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString());
@@ -513,6 +535,8 @@ public:
m_temporary_allocation = map.Malloc(data.GetByteSize(), byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error);
m_temporary_allocation_size = data.GetByteSize();
+ m_original_data.reset(new DataBufferHeap(data.GetDataStart(), data.GetByteSize()));
+
if (!alloc_error.Success())
{
err.SetErrorStringWithFormat("couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString());
@@ -585,14 +609,28 @@ public:
return;
}
- Error set_error;
+ bool actually_write = true;
- valobj_sp->SetData(data, set_error);
+ if (m_original_data)
+ {
+ if ((data.GetByteSize() == m_original_data->GetByteSize()) &&
+ !memcmp(m_original_data->GetBytes(), data.GetDataStart(), data.GetByteSize()))
+ {
+ actually_write = false;
+ }
+ }
- if (!set_error.Success())
+ Error set_error;
+
+ if (actually_write)
{
- err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString());
- return;
+ valobj_sp->SetData(data, set_error);
+
+ if (!set_error.Success())
+ {
+ err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString());
+ return;
+ }
}
Error free_error;
@@ -605,6 +643,7 @@ public:
return;
}
+ m_original_data.reset();
m_temporary_allocation = LLDB_INVALID_ADDRESS;
m_temporary_allocation_size = 0;
}
@@ -700,6 +739,7 @@ private:
bool m_is_reference;
lldb::addr_t m_temporary_allocation;
size_t m_temporary_allocation_size;
+ lldb::DataBufferSP m_original_data;
};
uint32_t
@@ -1312,43 +1352,44 @@ Materializer::DematerializerSP
Materializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error)
{
ExecutionContextScope *exe_scope = frame_sp.get();
-
+
if (!exe_scope)
exe_scope = map.GetBestExecutionContextScope();
-
+
DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
-
+
if (dematerializer_sp)
{
error.SetErrorToGenericError();
error.SetErrorString("Couldn't materialize: already materialized");
}
-
+
DematerializerSP ret(new Dematerializer(*this, frame_sp, map, process_address));
-
+
if (!exe_scope)
{
error.SetErrorToGenericError();
error.SetErrorString("Couldn't materialize: target doesn't exist");
}
-
+
for (EntityUP &entity_up : m_entities)
{
entity_up->Materialize(frame_sp, map, process_address, error);
-
+
if (!error.Success())
return DematerializerSP();
}
-
+
if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
{
- log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", frame_sp.get(), process_address);
+ log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:",
+ static_cast<void*>(frame_sp.get()), process_address);
for (EntityUP &entity_up : m_entities)
entity_up->DumpToLog(map, process_address, log);
}
-
+
m_dematerializer_wp = ret;
-
+
return ret;
}
@@ -1360,15 +1401,15 @@ Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpression
lldb::ThreadSP thread_sp = m_thread_wp.lock();
if (thread_sp)
frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
-
+
ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope();
-
+
if (!IsValid())
{
error.SetErrorToGenericError();
error.SetErrorString("Couldn't dematerialize: invalid dematerializer");
}
-
+
if (!exe_scope)
{
error.SetErrorToGenericError();
@@ -1378,11 +1419,12 @@ Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpression
{
if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
{
- log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:", frame_sp.get(), m_process_address);
+ log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:",
+ static_cast<void*>(frame_sp.get()), m_process_address);
for (EntityUP &entity_up : m_materializer->m_entities)
entity_up->DumpToLog(*m_map, m_process_address, log);
}
-
+
for (EntityUP &entity_up : m_materializer->m_entities)
{
if (entity_up.get() == m_materializer->m_result_entity)
@@ -1393,12 +1435,12 @@ Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpression
{
entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
}
-
+
if (!error.Success())
break;
}
}
-
+
Wipe();
}
diff --git a/source/Host/common/Condition.cpp b/source/Host/common/Condition.cpp
index 7bc6b6554648..1c1afb4add7e 100644
--- a/source/Host/common/Condition.cpp
+++ b/source/Host/common/Condition.cpp
@@ -57,11 +57,6 @@ Condition::Signal ()
return ::pthread_cond_signal (&m_condition);
}
-/* convert struct timeval to ms(milliseconds) */
-static unsigned long int tv2ms(struct timeval a) {
- return ((a.tv_sec * 1000) + (a.tv_usec / 1000));
-}
-
//----------------------------------------------------------------------
// The Wait() function atomically blocks the current thread
// waiting on the owned condition variable, and unblocks the mutex
diff --git a/source/Host/common/DynamicLibrary.cpp b/source/Host/common/DynamicLibrary.cpp
deleted file mode 100644
index 315a675895ff..000000000000
--- a/source/Host/common/DynamicLibrary.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===-- DynamicLibrary.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/DynamicLibrary.h"
-
-using namespace lldb_private;
-
-DynamicLibrary::DynamicLibrary (const FileSpec& spec, uint32_t options) : m_filespec(spec)
-{
- Error err;
- m_handle = Host::DynamicLibraryOpen (spec,options,err);
- if (err.Fail())
- m_handle = NULL;
-}
-
-bool
-DynamicLibrary::IsValid ()
-{
- return m_handle != NULL;
-}
-
-DynamicLibrary::~DynamicLibrary ()
-{
- if (m_handle)
- Host::DynamicLibraryClose (m_handle);
-}
diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp
index 679aadd54c4f..7af9f39a7863 100644
--- a/source/Host/common/Editline.cpp
+++ b/source/Host/common/Editline.cpp
@@ -20,30 +20,158 @@
using namespace lldb;
using namespace lldb_private;
+namespace lldb_private {
+ typedef std::weak_ptr<EditlineHistory> 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 ()
+ {
+ m_history = ::history_init();
+ ::history (m_history, &m_event, H_SETSIZE, size);
+ if (unique_entries)
+ ::history (m_history, &m_event, H_SETUNIQUE, 1);
+ }
+
+ const char *
+ GetHistoryFilePath()
+ {
+ if (m_path.empty() && m_history && !m_prefix.empty())
+ {
+ 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());
+ }
+ if (m_path.empty())
+ return NULL;
+ return m_path.c_str();
+ }
+
+ public:
+
+ ~EditlineHistory()
+ {
+ Save ();
+
+ if (m_history)
+ {
+ ::history_end (m_history);
+ m_history = NULL;
+ }
+ }
+
+ static EditlineHistorySP
+ GetHistory (const std::string &prefix)
+ {
+ typedef std::map<std::string, EditlineHistoryWP> 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;
+ }
+
+ 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)
+ {
+ const char *path = GetHistoryFilePath();
+ if (path)
+ {
+ ::history (m_history, &m_event, H_LOAD, path);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool
+ Save ()
+ {
+ if (m_history)
+ {
+ const char *path = GetHistoryFilePath();
+ if (path)
+ {
+ ::history (m_history, &m_event, H_SAVE, path);
+ return true;
+ }
+ }
+ 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
+ };
+}
+
+
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 (NULL),
- m_history_event (),
- m_program (),
+ m_history_sp (),
m_prompt (),
m_lines_prompt (),
- m_getc_buffer (),
- m_getc_mutex (Mutex::eMutexTypeNormal),
- m_getc_cond (),
-// m_gets_mutex (Mutex::eMutexTypeNormal),
+ 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),
@@ -51,14 +179,16 @@ Editline::Editline (const char *prog, // prog can't be NULL
{
if (prog && prog[0])
{
- m_program = prog;
m_editline = ::el_init(prog, fin, fout, ferr);
- m_history = ::history_init();
+
+ // Get a shared history instance
+ m_history_sp = EditlineHistory::GetHistory(prog);
}
else
{
m_editline = ::el_init("lldb-tmp", fin, fout, ferr);
}
+
if (prompt && prompt[0])
SetPrompt (prompt);
@@ -76,28 +206,44 @@ Editline::Editline (const char *prog, // prog can't be NULL
::el_set (m_editline, EL_PROMPT, GetPromptCallback);
#endif
::el_set (m_editline, EL_EDITOR, "emacs");
- if (m_history)
+ if (m_history_sp && m_history_sp->IsValid())
{
- ::el_set (m_editline, EL_HIST, history, m_history);
+ ::el_set (m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr());
}
::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);
::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 autocompelte
+ ::el_set (m_editline, EL_BIND, "\t", "lldb-complete", NULL); // Bind TAB to be auto complete
+
+ if (configure_for_multiline)
+ {
+ // 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
+ }
+ else
+ {
+ // 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
+ }
// Source $PWD/.editrc then $HOME/.editrc
::el_source (m_editline, NULL);
- if (m_history)
- {
- ::history (m_history, &m_history_event, H_SETSIZE, 800);
- ::history (m_history, &m_history_event, H_SETUNIQUE, 1);
- }
-
// 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
@@ -109,14 +255,12 @@ Editline::Editline (const char *prog, // prog can't be NULL
Editline::~Editline()
{
- SaveHistory();
-
- if (m_history)
- {
- ::history_end (m_history);
- m_history = NULL;
- }
-
+ // 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();
+
// 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.
@@ -132,36 +276,19 @@ Editline::SetGetCharCallback (GetCharCallbackType callback)
::el_set (m_editline, EL_GETCFN, callback);
}
-FileSpec
-Editline::GetHistoryFile()
-{
- char history_path[PATH_MAX];
- ::snprintf (history_path, sizeof(history_path), "~/.%s-history", m_program.c_str());
- return FileSpec(history_path, true);
-}
-
bool
Editline::LoadHistory ()
{
- if (m_history)
- {
- FileSpec history_file(GetHistoryFile());
- if (history_file.Exists())
- ::history (m_history, &m_history_event, H_LOAD, history_file.GetPath().c_str());
- return true;
- }
+ if (m_history_sp)
+ return m_history_sp->Load();
return false;
}
bool
Editline::SaveHistory ()
{
- if (m_history)
- {
- std::string history_path = GetHistoryFile().GetPath();
- ::history (m_history, &m_history_event, H_SAVE, history_path.c_str());
- return true;
- }
+ if (m_history_sp)
+ return m_history_sp->Save();
return false;
}
@@ -180,13 +307,8 @@ Editline::PrivateGetLine(std::string &line)
if (m_editline != NULL)
{
int line_len = 0;
- const char *line_cstr = NULL;
// Call el_gets to prompt the user and read the user's input.
-// {
-// // Make sure we know when we are in el_gets() by using a mutex
-// Mutex::Locker locker (m_gets_mutex);
- line_cstr = ::el_gets (m_editline, &line_len);
-// }
+ const char *line_cstr = ::el_gets (m_editline, &line_len);
static int save_errno = (line_len < 0) ? errno : 0;
@@ -198,20 +320,18 @@ Editline::PrivateGetLine(std::string &line)
{
// Decrement the length so we don't have newline characters in "line" for when
// we assign the cstr into the std::string
- while (line_len > 0 &&
- (line_cstr[line_len - 1] == '\n' ||
- line_cstr[line_len - 1] == '\r'))
- --line_len;
+ llvm::StringRef line_ref (line_cstr);
+ line_ref = line_ref.rtrim("\n\r");
- if (line_len > 0)
+ if (!line_ref.empty() && !m_interrupted)
{
// 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)
- ::history (m_history, &m_history_event, H_ENTER, line_cstr);
+ 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.assign(line_cstr, line_len);
+ line = std::move(line_ref.str());
}
}
}
@@ -224,15 +344,14 @@ Editline::PrivateGetLine(std::string &line)
Error
-Editline::GetLine(std::string &line)
+Editline::GetLine(std::string &line, bool &interrupted)
{
Error error;
+ interrupted = false;
line.clear();
// Set arrow key bindings for up and down arrows for single line
// mode where up and down arrows do prev/next history
- ::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
m_interrupted = false;
if (!m_got_eof)
@@ -252,6 +371,8 @@ Editline::GetLine(std::string &line)
m_getting_line = false;
}
+ interrupted = m_interrupted;
+
if (m_got_eof && line.empty())
{
// Only set the error if we didn't get an error back from PrivateGetLine()
@@ -278,9 +399,10 @@ Editline::Push (const char *bytes, size_t len)
Error
-Editline::GetLines(const std::string &end_line, StringList &lines)
+Editline::GetLines(const std::string &end_line, StringList &lines, bool &interrupted)
{
Error error;
+ interrupted = false;
if (m_getting_line)
{
error.SetErrorString("already getting a line");
@@ -294,10 +416,6 @@ Editline::GetLines(const std::string &end_line, StringList &lines)
// Set arrow key bindings for up and down arrows for multiple line
// mode where up and down arrows do edit prev/next line
- ::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
- ::el_set (m_editline, EL_BIND, "^b", "ed-prev-history", NULL);
- ::el_set (m_editline, EL_BIND, "^n", "ed-next-history", NULL);
m_interrupted = false;
LineStatus line_status = LineStatus::Success;
@@ -321,6 +439,11 @@ Editline::GetLines(const std::string &end_line, StringList &lines)
{
line_status = LineStatus::Error;
}
+ else if (m_interrupted)
+ {
+ interrupted = true;
+ line_status = LineStatus::Done;
+ }
else
{
switch (m_lines_command)
@@ -385,7 +508,7 @@ Editline::GetLines(const std::string &end_line, StringList &lines)
// If we have a callback, call it one more time to let the
// user know the lines are complete
- if (m_line_complete_callback)
+ if (m_line_complete_callback && !interrupted)
m_line_complete_callback (this,
lines,
UINT32_MAX,
@@ -599,70 +722,78 @@ Editline::GetPromptCallback (::EditLine *e)
return "";
}
-size_t
-Editline::SetInputBuffer (const char *c, size_t len)
-{
- if (c && len > 0)
- {
- Mutex::Locker locker(m_getc_mutex);
- SetGetCharCallback(GetCharInputBufferCallback);
- m_getc_buffer.append(c, len);
- m_getc_cond.Broadcast();
- }
- return len;
-}
-
-int
-Editline::GetChar (char *c)
-{
- Mutex::Locker locker(m_getc_mutex);
- if (m_getc_buffer.empty())
- m_getc_cond.Wait(m_getc_mutex);
- if (m_getc_buffer.empty())
- return 0;
- *c = m_getc_buffer[0];
- m_getc_buffer.erase(0,1);
- return 1;
-}
-
-int
-Editline::GetCharInputBufferCallback (EditLine *e, char *c)
-{
- Editline *editline = GetClientData (e);
- if (editline)
- return editline->GetChar(c);
- return 0;
-}
-
int
Editline::GetCharFromInputFileCallback (EditLine *e, char *c)
{
Editline *editline = GetClientData (e);
if (editline && editline->m_got_eof == false)
{
- char ch = ::fgetc(editline->GetInputFile());
- 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)
- {
- ch = EOF;
- }
- }
-
- if (ch == EOF)
+ FILE *f = editline->GetInputFile();
+ if (f == NULL)
{
editline->m_got_eof = true;
+ return 0;
}
- else
+
+
+ while (1)
{
- *c = ch;
- return 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;
+ }
+ }
}
}
return 0;
@@ -671,12 +802,23 @@ Editline::GetCharFromInputFileCallback (EditLine *e, char *c)
void
Editline::Hide ()
{
- FILE *out_file = GetOutputFile();
- if (out_file)
+ if (m_getting_line)
{
- 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));
+ // 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));
+ }
+ }
}
}
@@ -684,13 +826,25 @@ Editline::Hide ()
void
Editline::Refresh()
{
- ::el_set (m_editline, EL_REFRESH);
+ if (m_getting_line)
+ {
+ // 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))
+ {
+ ::el_set (m_editline, EL_REFRESH);
+ }
+ }
}
-void
+bool
Editline::Interrupt ()
{
m_interrupted = true;
if (m_getting_line || m_lines_curr_line > 0)
- el_insertstr(m_editline, "\n"); // True to force the line to complete itself so we get exit from el_gets()
+ return m_file.InterruptRead();
+ return false; // Interrupt not handled as we weren't getting a line or lines
}
diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp
index bb0ee39fbc7b..50513af2dc14 100644
--- a/source/Host/common/File.cpp
+++ b/source/Host/common/File.cpp
@@ -24,6 +24,7 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/FileSpec.h"
@@ -77,11 +78,11 @@ int File::kInvalidDescriptor = -1;
FILE * File::kInvalidStream = NULL;
File::File(const char *path, uint32_t options, uint32_t permissions) :
+ IOObject(eFDTypeFile, false),
m_descriptor (kInvalidDescriptor),
m_stream (kInvalidStream),
m_options (),
m_own_stream (false),
- m_own_descriptor (false),
m_is_interactive (eLazyBoolCalculate),
m_is_real_terminal (eLazyBoolCalculate)
{
@@ -91,11 +92,11 @@ File::File(const char *path, uint32_t options, uint32_t permissions) :
File::File (const FileSpec& filespec,
uint32_t options,
uint32_t permissions) :
+ IOObject(eFDTypeFile, false),
m_descriptor (kInvalidDescriptor),
m_stream (kInvalidStream),
m_options (0),
m_own_stream (false),
- m_own_descriptor (false),
m_is_interactive (eLazyBoolCalculate),
m_is_real_terminal (eLazyBoolCalculate)
@@ -107,11 +108,11 @@ File::File (const FileSpec& filespec,
}
File::File (const File &rhs) :
+ IOObject(eFDTypeFile, false),
m_descriptor (kInvalidDescriptor),
m_stream (kInvalidStream),
m_options (0),
m_own_stream (false),
- m_own_descriptor (false),
m_is_interactive (eLazyBoolCalculate),
m_is_real_terminal (eLazyBoolCalculate)
{
@@ -148,13 +149,20 @@ File::GetDescriptor() const
return kInvalidDescriptor;
}
+IOObject::WaitableHandle
+File::GetWaitableHandle()
+{
+ return m_descriptor;
+}
+
+
void
File::SetDescriptor (int fd, bool transfer_ownership)
{
if (IsValid())
Close();
m_descriptor = fd;
- m_own_descriptor = transfer_ownership;
+ m_should_close_fd = transfer_ownership;
}
@@ -168,7 +176,7 @@ File::GetStream ()
const char *mode = GetStreamOpenModeFromOptions (m_options);
if (mode)
{
- if (!m_own_descriptor)
+ if (!m_should_close_fd)
{
// We must duplicate the file descriptor if we don't own it because
// when you call fdopen, the stream will own the fd
@@ -177,7 +185,7 @@ File::GetStream ()
#else
m_descriptor = ::fcntl(GetDescriptor(), F_DUPFD);
#endif
- m_own_descriptor = true;
+ m_should_close_fd = true;
}
do
@@ -191,7 +199,7 @@ File::GetStream ()
if (m_stream)
{
m_own_stream = true;
- m_own_descriptor = false;
+ m_should_close_fd = false;
}
}
}
@@ -228,7 +236,7 @@ File::Duplicate (const File &rhs)
else
{
m_options = rhs.m_options;
- m_own_descriptor = true;
+ m_should_close_fd = true;
}
}
else
@@ -307,7 +315,7 @@ File::Open (const char *path, uint32_t options, uint32_t permissions)
error.SetErrorToErrno();
else
{
- m_own_descriptor = true;
+ m_should_close_fd = true;
m_options = options;
}
@@ -371,7 +379,7 @@ File::Close ()
error.SetErrorToErrno();
}
- if (DescriptorIsValid() && m_own_descriptor)
+ if (DescriptorIsValid() && m_should_close_fd)
{
if (::close (m_descriptor) != 0)
error.SetErrorToErrno();
@@ -380,7 +388,7 @@ File::Close ()
m_stream = kInvalidStream;
m_options = 0;
m_own_stream = false;
- m_own_descriptor = false;
+ m_should_close_fd = false;
m_is_interactive = eLazyBoolCalculate;
m_is_real_terminal = eLazyBoolCalculate;
return error;
@@ -669,6 +677,7 @@ File::Write (const void *buf, size_t &num_bytes)
num_bytes = 0;
error.SetErrorString("invalid file handle");
}
+
return error;
}
@@ -887,7 +896,13 @@ File::CalculateInteractiveAndTerminal ()
{
m_is_interactive = eLazyBoolNo;
m_is_real_terminal = eLazyBoolNo;
-#ifndef _MSC_VER
+#ifdef _WIN32
+ if (_isatty(fd))
+ {
+ m_is_interactive = eLazyBoolYes;
+ m_is_real_terminal = eLazyBoolYes;
+ }
+#else
if (isatty(fd))
{
m_is_interactive = eLazyBoolYes;
diff --git a/source/Host/common/FileCache.cpp b/source/Host/common/FileCache.cpp
new file mode 100644
index 000000000000..96b2a2ec02af
--- /dev/null
+++ b/source/Host/common/FileCache.cpp
@@ -0,0 +1,127 @@
+//===-- FileCache.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/FileCache.h"
+
+#include "lldb/Host/File.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+FileCache *FileCache::m_instance = nullptr;
+
+FileCache &
+FileCache::GetInstance()
+{
+ if (m_instance == nullptr)
+ m_instance = new FileCache();
+
+ return *m_instance;
+}
+
+lldb::user_id_t
+FileCache::OpenFile(const FileSpec &file_spec, uint32_t flags, uint32_t mode, Error &error)
+{
+ std::string path(file_spec.GetPath());
+ if (path.empty())
+ {
+ error.SetErrorString("empty path");
+ return UINT64_MAX;
+ }
+ FileSP file_sp(new File());
+ error = file_sp->Open(path.c_str(), flags, mode);
+ if (file_sp->IsValid() == false)
+ return UINT64_MAX;
+ lldb::user_id_t fd = file_sp->GetDescriptor();
+ m_cache[fd] = file_sp;
+ return fd;
+}
+
+bool
+FileCache::CloseFile(lldb::user_id_t fd, Error &error)
+{
+ if (fd == UINT64_MAX)
+ {
+ error.SetErrorString("invalid file descriptor");
+ return false;
+ }
+ FDToFileMap::iterator pos = m_cache.find(fd);
+ if (pos == m_cache.end())
+ {
+ error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
+ return false;
+ }
+ FileSP file_sp = pos->second;
+ if (!file_sp)
+ {
+ error.SetErrorString("invalid host backing file");
+ return false;
+ }
+ error = file_sp->Close();
+ m_cache.erase(pos);
+ return error.Success();
+}
+
+uint64_t
+FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset, const void *src, uint64_t src_len, Error &error)
+{
+ if (fd == UINT64_MAX)
+ {
+ error.SetErrorString("invalid file descriptor");
+ return UINT64_MAX;
+ }
+ FDToFileMap::iterator pos = m_cache.find(fd);
+ if (pos == m_cache.end())
+ {
+ error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
+ return false;
+ }
+ FileSP file_sp = pos->second;
+ if (!file_sp)
+ {
+ error.SetErrorString("invalid host backing file");
+ return UINT64_MAX;
+ }
+ if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset || error.Fail())
+ return UINT64_MAX;
+ size_t bytes_written = src_len;
+ error = file_sp->Write(src, bytes_written);
+ if (error.Fail())
+ return UINT64_MAX;
+ return bytes_written;
+}
+
+uint64_t
+FileCache::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, uint64_t dst_len, Error &error)
+{
+ if (fd == UINT64_MAX)
+ {
+ error.SetErrorString("invalid file descriptor");
+ return UINT64_MAX;
+ }
+ FDToFileMap::iterator pos = m_cache.find(fd);
+ if (pos == m_cache.end())
+ {
+ error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
+ return false;
+ }
+ FileSP file_sp = pos->second;
+ if (!file_sp)
+ {
+ error.SetErrorString("invalid host backing file");
+ return UINT64_MAX;
+ }
+ if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset || error.Fail())
+ return UINT64_MAX;
+ size_t bytes_read = dst_len;
+ error = file_sp->Read(dst, bytes_read);
+ if (error.Fail())
+ return UINT64_MAX;
+ return bytes_read;
+}
diff --git a/source/Host/common/FileSpec.cpp b/source/Host/common/FileSpec.cpp
index 48f1ac78d927..8c4014c074f5 100644
--- a/source/Host/common/FileSpec.cpp
+++ b/source/Host/common/FileSpec.cpp
@@ -27,21 +27,22 @@
#include <pwd.h>
#endif
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Program.h"
-
-#include "lldb/Core/StreamString.h"
-#include "lldb/Host/File.h"
-#include "lldb/Host/FileSpec.h"
-#include "lldb/Host/Host.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataBufferMemoryMap.h"
#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/StreamString.h"
#include "lldb/Core/Stream.h"
+#include "lldb/Host/File.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Utility/CleanUp.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -54,104 +55,68 @@ GetFileStats (const FileSpec *file_spec, struct stat *stats_ptr)
return false;
}
-#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
-
-static const char*
-GetCachedGlobTildeSlash()
-{
- static std::string g_tilde;
- if (g_tilde.empty())
- {
- struct passwd *user_entry;
- user_entry = getpwuid(geteuid());
- if (user_entry != NULL)
- g_tilde = user_entry->pw_dir;
-
- if (g_tilde.empty())
- return NULL;
- }
- return g_tilde.c_str();
-}
-
-#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
-
// Resolves the username part of a path of the form ~user/other/directories, and
// writes the result into dst_path.
-// Returns 0 if there WAS a ~ in the path but the username couldn't be resolved.
-// Otherwise returns the number of characters copied into dst_path. If the return
-// is >= dst_len, then the resolved path is too long...
-size_t
-FileSpec::ResolveUsername (const char *src_path, char *dst_path, size_t dst_len)
+void
+FileSpec::ResolveUsername (llvm::SmallVectorImpl<char> &path)
{
- if (src_path == NULL || src_path[0] == '\0')
- return 0;
-
-#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
-
- char user_home[PATH_MAX];
- const char *user_name;
-
-
- // If there's no ~, then just copy src_path straight to dst_path (they may be the same string...)
- if (src_path[0] != '~')
- {
- size_t len = strlen (src_path);
- if (len >= dst_len)
- {
- ::bcopy (src_path, dst_path, dst_len - 1);
- dst_path[dst_len] = '\0';
- }
- else
- ::bcopy (src_path, dst_path, len + 1);
-
- return len;
- }
-
- const char *first_slash = ::strchr (src_path, '/');
- char remainder[PATH_MAX];
+#if LLDB_CONFIG_TILDE_RESOLVES_TO_USER
+ if (path.empty() || path[0] != '~')
+ return;
- if (first_slash == NULL)
+ llvm::StringRef path_str(path.data());
+ size_t slash_pos = path_str.find_first_of("/", 1);
+ if (slash_pos == 1)
{
- // The whole name is the username (minus the ~):
- user_name = src_path + 1;
- remainder[0] = '\0';
- }
- else
- {
- size_t user_name_len = first_slash - src_path - 1;
- ::memcpy (user_home, src_path + 1, user_name_len);
- user_home[user_name_len] = '\0';
- user_name = user_home;
+ // A path of the form ~/ resolves to the current user's home dir
+ llvm::SmallString<64> home_dir;
+ if (!llvm::sys::path::home_directory(home_dir))
+ return;
- ::strcpy (remainder, first_slash);
+ // Overwrite the ~ with the first character of the homedir, and insert
+ // the rest. This way we only trigger one move, whereas an insert
+ // followed by a delete (or vice versa) would trigger two.
+ path[0] = home_dir[0];
+ path.insert(path.begin() + 1, home_dir.begin() + 1, home_dir.end());
+ return;
}
- if (user_name == NULL)
- return 0;
- // User name of "" means the current user...
-
- struct passwd *user_entry;
- const char *home_dir = NULL;
-
- if (user_name[0] == '\0')
+ auto username_begin = path.begin()+1;
+ auto username_end = (slash_pos == llvm::StringRef::npos)
+ ? path.end()
+ : (path.begin() + slash_pos);
+ size_t replacement_length = std::distance(path.begin(), username_end);
+
+ llvm::SmallString<20> username(username_begin, username_end);
+ struct passwd *user_entry = ::getpwnam(username.c_str());
+ if (user_entry != nullptr)
{
- home_dir = GetCachedGlobTildeSlash();
+ // Copy over the first n characters of the path, where n is the smaller of the length
+ // of the home directory and the slash pos.
+ llvm::StringRef homedir(user_entry->pw_dir);
+ size_t initial_copy_length = std::min(homedir.size(), replacement_length);
+ auto src_begin = homedir.begin();
+ auto src_end = src_begin + initial_copy_length;
+ std::copy(src_begin, src_end, path.begin());
+ if (replacement_length > homedir.size())
+ {
+ // We copied the entire home directory, but the ~username portion of the path was
+ // longer, so there's characters that need to be removed.
+ path.erase(path.begin() + initial_copy_length, username_end);
+ }
+ else if (replacement_length < homedir.size())
+ {
+ // We copied all the way up to the slash in the destination, but there's still more
+ // characters that need to be inserted.
+ path.insert(username_end, src_end, homedir.end());
+ }
}
else
{
- user_entry = ::getpwnam (user_name);
- if (user_entry != NULL)
- home_dir = user_entry->pw_dir;
+ // Unable to resolve username (user doesn't exist?)
+ path.clear();
}
-
- if (home_dir == NULL)
- return 0;
- else
- return ::snprintf (dst_path, dst_len, "%s%s", home_dir, remainder);
-#else
- // Resolving home directories is not supported, just copy the path...
- return ::snprintf (dst_path, dst_len, "%s", src_path);
-#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
+#endif
}
size_t
@@ -187,49 +152,24 @@ FileSpec::ResolvePartialUsername (const char *partial_name, StringList &matches)
#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
}
-
-
-size_t
-FileSpec::Resolve (const char *src_path, char *dst_path, size_t dst_len)
+void
+FileSpec::Resolve (llvm::SmallVectorImpl<char> &path)
{
- if (src_path == NULL || src_path[0] == '\0')
- return 0;
+ if (path.empty())
+ return;
- // Glob if needed for ~/, otherwise copy in case src_path is same as dst_path...
- char unglobbed_path[PATH_MAX];
#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
- if (src_path[0] == '~')
- {
- size_t return_count = ResolveUsername(src_path, unglobbed_path, sizeof(unglobbed_path));
-
- // If we couldn't find the user referred to, or the resultant path was too long,
- // then just copy over the src_path.
- if (return_count == 0 || return_count >= sizeof(unglobbed_path))
- ::snprintf (unglobbed_path, sizeof(unglobbed_path), "%s", src_path);
- }
- else
+ if (path[0] == '~')
+ ResolveUsername(path);
#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
- {
- ::snprintf(unglobbed_path, sizeof(unglobbed_path), "%s", src_path);
- }
- // Now resolve the path if needed
- char resolved_path[PATH_MAX];
- if (::realpath (unglobbed_path, resolved_path))
- {
- // Success, copy the resolved path
- return ::snprintf(dst_path, dst_len, "%s", resolved_path);
- }
- else
- {
- // Failed, just copy the unglobbed path
- return ::snprintf(dst_path, dst_len, "%s", unglobbed_path);
- }
+ llvm::sys::fs::make_absolute(path);
}
-FileSpec::FileSpec() :
- m_directory(),
- m_filename()
+FileSpec::FileSpec()
+ : m_directory()
+ , m_filename()
+ , m_syntax(FileSystem::GetNativePathSyntax())
{
}
@@ -237,13 +177,13 @@ FileSpec::FileSpec() :
// Default constructor that can take an optional full path to a
// file on disk.
//------------------------------------------------------------------
-FileSpec::FileSpec(const char *pathname, bool resolve_path) :
+FileSpec::FileSpec(const char *pathname, bool resolve_path, PathSyntax syntax) :
m_directory(),
m_filename(),
m_is_resolved(false)
{
if (pathname && pathname[0])
- SetFile(pathname, resolve_path);
+ SetFile(pathname, resolve_path, syntax);
}
//------------------------------------------------------------------
@@ -252,7 +192,8 @@ FileSpec::FileSpec(const char *pathname, bool resolve_path) :
FileSpec::FileSpec(const FileSpec& rhs) :
m_directory (rhs.m_directory),
m_filename (rhs.m_filename),
- m_is_resolved (rhs.m_is_resolved)
+ m_is_resolved (rhs.m_is_resolved),
+ m_syntax (rhs.m_syntax)
{
}
@@ -268,7 +209,7 @@ FileSpec::FileSpec(const FileSpec* rhs) :
}
//------------------------------------------------------------------
-// Virtual destrcuctor in case anyone inherits from this class.
+// Virtual destructor in case anyone inherits from this class.
//------------------------------------------------------------------
FileSpec::~FileSpec()
{
@@ -285,83 +226,65 @@ FileSpec::operator= (const FileSpec& rhs)
m_directory = rhs.m_directory;
m_filename = rhs.m_filename;
m_is_resolved = rhs.m_is_resolved;
+ m_syntax = rhs.m_syntax;
}
return *this;
}
+void FileSpec::Normalize(llvm::SmallVectorImpl<char> &path, PathSyntax syntax)
+{
+ if (syntax == ePathSyntaxPosix ||
+ (syntax == ePathSyntaxHostNative && FileSystem::GetNativePathSyntax() == ePathSyntaxPosix))
+ return;
+
+ std::replace(path.begin(), path.end(), '\\', '/');
+}
+
+void FileSpec::DeNormalize(llvm::SmallVectorImpl<char> &path, PathSyntax syntax)
+{
+ if (syntax == ePathSyntaxPosix ||
+ (syntax == ePathSyntaxHostNative && FileSystem::GetNativePathSyntax() == ePathSyntaxPosix))
+ return;
+
+ std::replace(path.begin(), path.end(), '/', '\\');
+}
+
//------------------------------------------------------------------
// Update the contents of this object with a new path. The path will
// be split up into a directory and filename and stored as uniqued
// string values for quick comparison and efficient memory usage.
//------------------------------------------------------------------
void
-FileSpec::SetFile (const char *pathname, bool resolve)
+FileSpec::SetFile (const char *pathname, bool resolve, PathSyntax syntax)
{
m_filename.Clear();
m_directory.Clear();
m_is_resolved = false;
+ m_syntax = (syntax == ePathSyntaxHostNative) ? FileSystem::GetNativePathSyntax() : syntax;
+
if (pathname == NULL || pathname[0] == '\0')
return;
- char resolved_path[PATH_MAX];
- bool path_fit = true;
-
+ llvm::SmallString<64> normalized(pathname);
+ Normalize(normalized, syntax);
+
if (resolve)
{
- path_fit = (FileSpec::Resolve (pathname, resolved_path, sizeof(resolved_path)) < sizeof(resolved_path) - 1);
- m_is_resolved = path_fit;
+ FileSpec::Resolve (normalized);
+ m_is_resolved = true;
}
- else
- {
- // Copy the path because "basename" and "dirname" want to muck with the
- // path buffer
- if (::strlen (pathname) > sizeof(resolved_path) - 1)
- path_fit = false;
- else
- ::strcpy (resolved_path, pathname);
- }
-
- if (path_fit)
+ llvm::StringRef resolve_path_ref(normalized.c_str());
+ llvm::StringRef filename_ref = llvm::sys::path::filename(resolve_path_ref);
+ if (!filename_ref.empty())
{
- char *filename = ::basename (resolved_path);
- if (filename)
- {
- m_filename.SetCString (filename);
- // Truncate the basename off the end of the resolved path
-
- // Only attempt to get the dirname if it looks like we have a path
- if (strchr(resolved_path, '/')
-#ifdef _WIN32
- || strchr(resolved_path, '\\')
-#endif
- )
- {
- char *directory = ::dirname (resolved_path);
-
- // Make sure we didn't get our directory resolved to "." without having
- // specified
- if (directory)
- m_directory.SetCString(directory);
- else
- {
- char *last_resolved_path_slash = strrchr(resolved_path, '/');
-#ifdef _WIN32
- char* last_resolved_path_slash_windows = strrchr(resolved_path, '\\');
- if (last_resolved_path_slash_windows > last_resolved_path_slash)
- last_resolved_path_slash = last_resolved_path_slash_windows;
-#endif
- if (last_resolved_path_slash)
- {
- *last_resolved_path_slash = '\0';
- m_directory.SetCString(resolved_path);
- }
- }
- }
- }
- else
- m_directory.SetCString(resolved_path);
+ m_filename.SetString (filename_ref);
+ llvm::StringRef directory_ref = llvm::sys::path::parent_path(resolve_path_ref);
+ if (!directory_ref.empty())
+ m_directory.SetString(directory_ref);
}
+ else
+ m_directory.SetCString(normalized.c_str());
}
//----------------------------------------------------------------------
@@ -562,6 +485,15 @@ FileSpec::Exists () const
}
bool
+FileSpec::Readable () const
+{
+ const uint32_t permissions = GetPermissions();
+ if (permissions & eFilePermissionsEveryoneR)
+ return true;
+ return false;
+}
+
+bool
FileSpec::ResolveExecutableLocation ()
{
if (!m_directory)
@@ -572,8 +504,7 @@ FileSpec::ResolveExecutableLocation ()
const std::string file_str (file_cstr);
std::string path = llvm::sys::FindProgramByName (file_str);
llvm::StringRef dir_ref = llvm::sys::path::parent_path(path);
- //llvm::StringRef dir_ref = path.getDirname();
- if (! dir_ref.empty())
+ if (!dir_ref.empty())
{
// FindProgramByName returns "." if it can't find the file.
if (strcmp (".", dir_ref.data()) == 0)
@@ -607,7 +538,7 @@ FileSpec::ResolvePath ()
return true; // We have already resolved this path
char path_buf[PATH_MAX];
- if (!GetPath (path_buf, PATH_MAX))
+ if (!GetPath (path_buf, PATH_MAX, false))
return false;
// SetFile(...) will set m_is_resolved correctly if it can resolve the path
SetFile (path_buf, true);
@@ -623,6 +554,12 @@ FileSpec::GetByteSize() const
return 0;
}
+FileSpec::PathSyntax
+FileSpec::GetPathSyntax() const
+{
+ return m_syntax;
+}
+
FileSpec::FileType
FileSpec::GetFileType () const
{
@@ -652,7 +589,7 @@ FileSpec::GetPermissions () const
{
uint32_t file_permissions = 0;
if (*this)
- Host::GetFilePermissions(GetPath().c_str(), file_permissions);
+ FileSystem::GetFilePermissions(GetPath().c_str(), file_permissions);
return file_permissions;
}
@@ -708,45 +645,30 @@ FileSpec::GetFilename() const
// values.
//------------------------------------------------------------------
size_t
-FileSpec::GetPath(char *path, size_t path_max_len) const
+FileSpec::GetPath(char *path, size_t path_max_len, bool denormalize) const
{
- if (path_max_len)
- {
- const char *dirname = m_directory.GetCString();
- const char *filename = m_filename.GetCString();
- if (dirname)
- {
- if (filename)
- return ::snprintf (path, path_max_len, "%s/%s", dirname, filename);
- else
- return ::snprintf (path, path_max_len, "%s", dirname);
- }
- else if (filename)
- {
- return ::snprintf (path, path_max_len, "%s", filename);
- }
- }
- if (path)
- path[0] = '\0';
- return 0;
+ if (!path)
+ return 0;
+
+ std::string result = GetPath(denormalize);
+
+ size_t result_length = std::min(path_max_len-1, result.length());
+ ::strncpy(path, result.c_str(), result_length + 1);
+ return result_length;
}
std::string
-FileSpec::GetPath (void) const
+FileSpec::GetPath (bool denormalize) const
{
- static ConstString g_slash_only ("/");
- std::string path;
- const char *dirname = m_directory.GetCString();
- const char *filename = m_filename.GetCString();
- if (dirname)
- {
- path.append (dirname);
- if (filename && m_directory != g_slash_only)
- path.append ("/");
- }
- if (filename)
- path.append (filename);
- return path;
+ llvm::SmallString<64> result;
+ if (m_directory)
+ result.append(m_directory.GetCString());
+ if (m_filename)
+ llvm::sys::path::append(result, m_filename.GetCString());
+ if (denormalize && !result.empty())
+ DeNormalize(result, m_syntax);
+
+ return std::string(result.begin(), result.end());
}
ConstString
@@ -780,7 +702,7 @@ FileSpec::GetFileNameStrippingExtension () const
// Returns a shared pointer to a data buffer that contains all or
// part of the contents of a file. The data is memory mapped and
// will lazily page in data from the file as memory is accessed.
-// The data that is mappped will start "file_offset" bytes into the
+// The data that is mapped will start "file_offset" bytes into the
// file, and "file_size" bytes will be mapped. If "file_size" is
// greater than the number of bytes available in the file starting
// at "file_offset", the number of bytes will be appropriately
@@ -936,12 +858,11 @@ FileSpec::EnumerateDirectory
if (dir_path && dir_path[0])
{
#if _WIN32
- char szDir[MAX_PATH];
- strcpy_s(szDir, MAX_PATH, dir_path);
- strcat_s(szDir, MAX_PATH, "\\*");
+ std::string szDir(dir_path);
+ szDir += "\\*";
WIN32_FIND_DATA ffd;
- HANDLE hFind = FindFirstFile(szDir, &ffd);
+ HANDLE hFind = FindFirstFile(szDir.c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE)
{
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp
index d43221c0e136..00c2fa37b383 100644
--- a/source/Host/common/Host.cpp
+++ b/source/Host/common/Host.cpp
@@ -12,11 +12,12 @@
// C includes
#include <errno.h>
#include <limits.h>
+#include <stdlib.h>
#include <sys/types.h>
#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
#include <winsock2.h>
-#include <WS2tcpip.h>
+#include <ws2tcpip.h>
#else
#include <unistd.h>
#include <dlfcn.h>
@@ -35,10 +36,9 @@
#include <mach/mach_port.h>
#include <mach/mach_init.h>
#include <mach-o/dyld.h>
-#include <AvailabilityMacros.h>
#endif
-#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)
+#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__) || defined(__NetBSD__)
#include <spawn.h>
#include <sys/wait.h>
#include <sys/syscall.h>
@@ -48,7 +48,11 @@
#include <pthread_np.h>
#endif
+// C++ includes
+#include <limits>
+
#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"
@@ -60,13 +64,19 @@
#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/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 (__APPLE__)
@@ -85,6 +95,12 @@ 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<uint32_t>::max ();
+#endif
#if !defined (__APPLE__) && !defined (_WIN32)
struct MonitorInfo
@@ -116,7 +132,18 @@ Host::StartMonitoringChildProcess
info_ptr->monitor_signals = monitor_signals;
char thread_name[256];
- ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%" PRIu64 ")>", pid);
+
+ 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), "<lldb.host.wait4(pid=%" PRIu64 ")>", pid);
+ }
+
thread = ThreadCreate (thread_name,
MonitorChildProcessThreadFunction,
info_ptr,
@@ -168,7 +195,7 @@ MonitorChildProcessThreadFunction (void *arg)
const bool monitor_signals = info->monitor_signals;
assert (info->pid <= UINT32_MAX);
- const ::pid_t pid = monitor_signals ? -1 * info->pid : info->pid;
+ const ::pid_t pid = monitor_signals ? -1 * getpgid(info->pid) : info->pid;
delete info;
@@ -302,181 +329,6 @@ Host::SystemLog (SystemLogType type, const char *format, ...)
va_end (args);
}
-const ArchSpec &
-Host::GetArchitecture (SystemDefaultArchitecture arch_kind)
-{
- static bool g_supports_32 = false;
- static bool g_supports_64 = false;
- static ArchSpec g_host_arch_32;
- static ArchSpec g_host_arch_64;
-
-#if defined (__APPLE__)
-
- // Apple is different in that it can support both 32 and 64 bit executables
- // in the same operating system running concurrently. Here we detect the
- // correct host architectures for both 32 and 64 bit including if 64 bit
- // executables are supported on the system.
-
- if (g_supports_32 == false && g_supports_64 == false)
- {
- // All apple systems support 32 bit execution.
- g_supports_32 = true;
- uint32_t cputype, cpusubtype;
- uint32_t is_64_bit_capable = false;
- size_t len = sizeof(cputype);
- ArchSpec host_arch;
- // These will tell us about the kernel architecture, which even on a 64
- // bit machine can be 32 bit...
- if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
- {
- len = sizeof (cpusubtype);
- if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0)
- cpusubtype = CPU_TYPE_ANY;
-
- len = sizeof (is_64_bit_capable);
- if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
- {
- if (is_64_bit_capable)
- g_supports_64 = true;
- }
-
- if (is_64_bit_capable)
- {
-#if defined (__i386__) || defined (__x86_64__)
- if (cpusubtype == CPU_SUBTYPE_486)
- cpusubtype = CPU_SUBTYPE_I386_ALL;
-#endif
- if (cputype & CPU_ARCH_ABI64)
- {
- // We have a 64 bit kernel on a 64 bit system
- g_host_arch_32.SetArchitecture (eArchTypeMachO, ~(CPU_ARCH_MASK) & cputype, cpusubtype);
- g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype);
- }
- else
- {
- // We have a 32 bit kernel on a 64 bit system
- g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype);
- cputype |= CPU_ARCH_ABI64;
- g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype);
- }
- }
- else
- {
- g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype);
- g_host_arch_64.Clear();
- }
- }
- }
-
-#else // #if defined (__APPLE__)
-
- if (g_supports_32 == false && g_supports_64 == false)
- {
- llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
-
- g_host_arch_32.Clear();
- g_host_arch_64.Clear();
-
- // If the OS is Linux, "unknown" in the vendor slot isn't what we want
- // for the default triple. It's probably an artifact of config.guess.
- if (triple.getOS() == llvm::Triple::Linux && triple.getVendor() == llvm::Triple::UnknownVendor)
- triple.setVendorName ("");
-
- const char* distribution_id = GetDistributionId ().AsCString();
-
- switch (triple.getArch())
- {
- default:
- g_host_arch_32.SetTriple(triple);
- g_host_arch_32.SetDistributionId (distribution_id);
- g_supports_32 = true;
- break;
-
- case llvm::Triple::x86_64:
- g_host_arch_64.SetTriple(triple);
- g_host_arch_64.SetDistributionId (distribution_id);
- g_supports_64 = true;
- g_host_arch_32.SetTriple(triple.get32BitArchVariant());
- g_host_arch_32.SetDistributionId (distribution_id);
- g_supports_32 = true;
- break;
-
- case llvm::Triple::sparcv9:
- case llvm::Triple::ppc64:
- g_host_arch_64.SetTriple(triple);
- g_host_arch_64.SetDistributionId (distribution_id);
- g_supports_64 = true;
- break;
- }
-
- g_supports_32 = g_host_arch_32.IsValid();
- g_supports_64 = g_host_arch_64.IsValid();
- }
-
-#endif // #else for #if defined (__APPLE__)
-
- if (arch_kind == eSystemDefaultArchitecture32)
- return g_host_arch_32;
- else if (arch_kind == eSystemDefaultArchitecture64)
- return g_host_arch_64;
-
- if (g_supports_64)
- return g_host_arch_64;
-
- return g_host_arch_32;
-}
-
-const ConstString &
-Host::GetVendorString()
-{
- static ConstString g_vendor;
- if (!g_vendor)
- {
- const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture);
- const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName();
- g_vendor.SetCStringWithLength(str_ref.data(), str_ref.size());
- }
- return g_vendor;
-}
-
-const ConstString &
-Host::GetOSString()
-{
- static ConstString g_os_string;
- if (!g_os_string)
- {
- const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture);
- const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName();
- g_os_string.SetCStringWithLength(str_ref.data(), str_ref.size());
- }
- return g_os_string;
-}
-
-const ConstString &
-Host::GetTargetTriple()
-{
- static ConstString g_host_triple;
- if (!(g_host_triple))
- {
- const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture);
- g_host_triple.SetCString(host_arch.GetTriple().getTriple().c_str());
- }
- return g_host_triple;
-}
-
-// See linux/Host.cpp for Linux-based implementations of this.
-// Add your platform-specific implementation to the appropriate host file.
-#if !defined(__linux__)
-
-const ConstString &
- Host::GetDistributionId ()
-{
- static ConstString s_distribution_id;
- return s_distribution_id;
-}
-
-#endif // #if !defined(__linux__)
-
lldb::pid_t
Host::GetCurrentProcessID()
{
@@ -806,51 +658,6 @@ Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid,
#endif
-FileSpec
-Host::GetProgramFileSpec ()
-{
- static FileSpec g_program_filespec;
- if (!g_program_filespec)
- {
-#if defined (__APPLE__)
- char program_fullpath[PATH_MAX];
- // If DST is NULL, then return the number of bytes needed.
- uint32_t len = sizeof(program_fullpath);
- int err = _NSGetExecutablePath (program_fullpath, &len);
- if (err == 0)
- g_program_filespec.SetFile (program_fullpath, false);
- else if (err == -1)
- {
- char *large_program_fullpath = (char *)::malloc (len + 1);
-
- err = _NSGetExecutablePath (large_program_fullpath, &len);
- if (err == 0)
- g_program_filespec.SetFile (large_program_fullpath, false);
-
- ::free (large_program_fullpath);
- }
-#elif defined (__linux__)
- char exe_path[PATH_MAX];
- ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
- if (len > 0) {
- exe_path[len] = 0;
- g_program_filespec.SetFile(exe_path, false);
- }
-#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
- int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() };
- size_t exe_path_size;
- if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0)
- {
- char *exe_path = new char[exe_path_size];
- if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0)
- g_program_filespec.SetFile(exe_path, false);
- delete[] exe_path;
- }
-#endif
- }
- return g_program_filespec;
-}
-
#if !defined (__APPLE__) // see Host.mm
bool
@@ -869,130 +676,6 @@ Host::ResolveExecutableInBundle (FileSpec &file)
#ifndef _WIN32
-// Opaque info that tracks a dynamic library that was loaded
-struct DynamicLibraryInfo
-{
- DynamicLibraryInfo (const FileSpec &fs, int o, void *h) :
- file_spec (fs),
- open_options (o),
- handle (h)
- {
- }
-
- const FileSpec file_spec;
- uint32_t open_options;
- void * handle;
-};
-
-void *
-Host::DynamicLibraryOpen (const FileSpec &file_spec, uint32_t options, Error &error)
-{
- char path[PATH_MAX];
- if (file_spec.GetPath(path, sizeof(path)))
- {
- int mode = 0;
-
- if (options & eDynamicLibraryOpenOptionLazy)
- mode |= RTLD_LAZY;
- else
- mode |= RTLD_NOW;
-
-
- if (options & eDynamicLibraryOpenOptionLocal)
- mode |= RTLD_LOCAL;
- else
- mode |= RTLD_GLOBAL;
-
-#ifdef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED
- if (options & eDynamicLibraryOpenOptionLimitGetSymbol)
- mode |= RTLD_FIRST;
-#endif
-
- void * opaque = ::dlopen (path, mode);
-
- if (opaque)
- {
- error.Clear();
- return new DynamicLibraryInfo (file_spec, options, opaque);
- }
- else
- {
- error.SetErrorString(::dlerror());
- }
- }
- else
- {
- error.SetErrorString("failed to extract path");
- }
- return NULL;
-}
-
-Error
-Host::DynamicLibraryClose (void *opaque)
-{
- Error error;
- if (opaque == NULL)
- {
- error.SetErrorString ("invalid dynamic library handle");
- }
- else
- {
- DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque;
- if (::dlclose (dylib_info->handle) != 0)
- {
- error.SetErrorString(::dlerror());
- }
-
- dylib_info->open_options = 0;
- dylib_info->handle = 0;
- delete dylib_info;
- }
- return error;
-}
-
-void *
-Host::DynamicLibraryGetSymbol (void *opaque, const char *symbol_name, Error &error)
-{
- if (opaque == NULL)
- {
- error.SetErrorString ("invalid dynamic library handle");
- }
- else
- {
- DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque;
-
- void *symbol_addr = ::dlsym (dylib_info->handle, symbol_name);
- if (symbol_addr)
- {
-#ifndef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED
- // This host doesn't support limiting searches to this shared library
- // so we need to verify that the match came from this shared library
- // if it was requested in the Host::DynamicLibraryOpen() function.
- if (dylib_info->open_options & eDynamicLibraryOpenOptionLimitGetSymbol)
- {
- FileSpec match_dylib_spec (Host::GetModuleFileSpecForHostAddress (symbol_addr));
- if (match_dylib_spec != dylib_info->file_spec)
- {
- char dylib_path[PATH_MAX];
- if (dylib_info->file_spec.GetPath (dylib_path, sizeof(dylib_path)))
- error.SetErrorStringWithFormat ("symbol not found in \"%s\"", dylib_path);
- else
- error.SetErrorString ("symbol not found");
- return NULL;
- }
- }
-#endif
- error.Clear();
- return symbol_addr;
- }
- else
- {
- error.SetErrorString(::dlerror());
- }
- }
- return NULL;
-}
-
FileSpec
Host::GetModuleFileSpecForHostAddress (const void *host_addr)
{
@@ -1008,427 +691,6 @@ Host::GetModuleFileSpecForHostAddress (const void *host_addr)
#endif
-bool
-Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
-{
- // To get paths related to LLDB we get the path to the executable that
- // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
- // on linux this is assumed to be the "lldb" main executable. If LLDB on
- // linux is actually in a shared library (liblldb.so) then this function will
- // need to be modified to "do the right thing".
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST);
-
- switch (path_type)
- {
- case ePathTypeLLDBShlibDir:
- {
- static ConstString g_lldb_so_dir;
- if (!g_lldb_so_dir)
- {
- FileSpec lldb_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)Host::GetLLDBPath));
- g_lldb_so_dir = lldb_file_spec.GetDirectory();
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_lldb_so_dir.GetCString());
- }
- file_spec.GetDirectory() = g_lldb_so_dir;
- return (bool)file_spec.GetDirectory();
- }
- break;
-
- case ePathTypeSupportExecutableDir:
- {
- static ConstString g_lldb_support_exe_dir;
- if (!g_lldb_support_exe_dir)
- {
- FileSpec lldb_file_spec;
- if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
- {
- char raw_path[PATH_MAX];
- char resolved_path[PATH_MAX];
- lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
-
-#if defined (__APPLE__)
- char *framework_pos = ::strstr (raw_path, "LLDB.framework");
- if (framework_pos)
- {
- framework_pos += strlen("LLDB.framework");
-#if defined (__arm__)
- // Shallow bundle
- *framework_pos = '\0';
-#else
- // Normal bundle
- ::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path));
-#endif
- }
-#endif
- FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
- g_lldb_support_exe_dir.SetCString(resolved_path);
- }
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", g_lldb_support_exe_dir.GetCString());
- }
- file_spec.GetDirectory() = g_lldb_support_exe_dir;
- return (bool)file_spec.GetDirectory();
- }
- break;
-
- case ePathTypeHeaderDir:
- {
- static ConstString g_lldb_headers_dir;
- if (!g_lldb_headers_dir)
- {
-#if defined (__APPLE__)
- FileSpec lldb_file_spec;
- if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
- {
- char raw_path[PATH_MAX];
- char resolved_path[PATH_MAX];
- lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
-
- char *framework_pos = ::strstr (raw_path, "LLDB.framework");
- if (framework_pos)
- {
- framework_pos += strlen("LLDB.framework");
- ::strncpy (framework_pos, "/Headers", PATH_MAX - (framework_pos - raw_path));
- }
- FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
- g_lldb_headers_dir.SetCString(resolved_path);
- }
-#else
- // TODO: Anyone know how we can determine this for linux? Other systems??
- g_lldb_headers_dir.SetCString ("/opt/local/include/lldb");
-#endif
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_lldb_headers_dir.GetCString());
- }
- file_spec.GetDirectory() = g_lldb_headers_dir;
- return (bool)file_spec.GetDirectory();
- }
- break;
-
-#ifdef LLDB_DISABLE_PYTHON
- case ePathTypePythonDir:
- return false;
-#else
- case ePathTypePythonDir:
- {
- static ConstString g_lldb_python_dir;
- if (!g_lldb_python_dir)
- {
- FileSpec lldb_file_spec;
- if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
- {
- char raw_path[PATH_MAX];
- char resolved_path[PATH_MAX];
- lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
-
-#if defined (__APPLE__)
- char *framework_pos = ::strstr (raw_path, "LLDB.framework");
- if (framework_pos)
- {
- framework_pos += strlen("LLDB.framework");
- ::strncpy (framework_pos, "/Resources/Python", PATH_MAX - (framework_pos - raw_path));
- }
- else
- {
-#endif
- llvm::SmallString<256> python_version_dir;
- llvm::raw_svector_ostream os(python_version_dir);
- os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION << "/site-packages";
- os.flush();
-
- // We may get our string truncated. Should we protect
- // this with an assert?
-
- ::strncat(raw_path, python_version_dir.c_str(),
- sizeof(raw_path) - strlen(raw_path) - 1);
-
-#if defined (__APPLE__)
- }
-#endif
- FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
- g_lldb_python_dir.SetCString(resolved_path);
- }
-
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypePythonDir) => '%s'", g_lldb_python_dir.GetCString());
-
- }
- file_spec.GetDirectory() = g_lldb_python_dir;
- return (bool)file_spec.GetDirectory();
- }
- break;
-#endif
-
- case ePathTypeLLDBSystemPlugins: // System plug-ins directory
- {
-#if defined (__APPLE__) || defined(__linux__)
- static ConstString g_lldb_system_plugin_dir;
- static bool g_lldb_system_plugin_dir_located = false;
- if (!g_lldb_system_plugin_dir_located)
- {
- g_lldb_system_plugin_dir_located = true;
-#if defined (__APPLE__)
- FileSpec lldb_file_spec;
- if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
- {
- char raw_path[PATH_MAX];
- char resolved_path[PATH_MAX];
- lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
-
- char *framework_pos = ::strstr (raw_path, "LLDB.framework");
- if (framework_pos)
- {
- framework_pos += strlen("LLDB.framework");
- ::strncpy (framework_pos, "/Resources/PlugIns", PATH_MAX - (framework_pos - raw_path));
- FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
- g_lldb_system_plugin_dir.SetCString(resolved_path);
- }
- return false;
- }
-#elif defined (__linux__)
- FileSpec lldb_file_spec("/usr/lib/lldb", true);
- if (lldb_file_spec.Exists())
- {
- g_lldb_system_plugin_dir.SetCString(lldb_file_spec.GetPath().c_str());
- }
-#endif // __APPLE__ || __linux__
-
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", g_lldb_system_plugin_dir.GetCString());
-
- }
-
- if (g_lldb_system_plugin_dir)
- {
- file_spec.GetDirectory() = g_lldb_system_plugin_dir;
- return true;
- }
-#else
- // TODO: where would system LLDB plug-ins be located on other systems?
- return false;
-#endif
- }
- break;
-
- case ePathTypeLLDBUserPlugins: // User plug-ins directory
- {
-#if defined (__APPLE__)
- static ConstString g_lldb_user_plugin_dir;
- if (!g_lldb_user_plugin_dir)
- {
- char user_plugin_path[PATH_MAX];
- if (FileSpec::Resolve ("~/Library/Application Support/LLDB/PlugIns",
- user_plugin_path,
- sizeof(user_plugin_path)))
- {
- g_lldb_user_plugin_dir.SetCString(user_plugin_path);
- }
- }
- file_spec.GetDirectory() = g_lldb_user_plugin_dir;
- return (bool)file_spec.GetDirectory();
-#elif defined (__linux__)
- static ConstString g_lldb_user_plugin_dir;
- if (!g_lldb_user_plugin_dir)
- {
- // XDG Base Directory Specification
- // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
- // If XDG_DATA_HOME exists, use that, otherwise use ~/.local/share/lldb.
- FileSpec lldb_file_spec;
- const char *xdg_data_home = getenv("XDG_DATA_HOME");
- if (xdg_data_home && xdg_data_home[0])
- {
- std::string user_plugin_dir (xdg_data_home);
- user_plugin_dir += "/lldb";
- lldb_file_spec.SetFile (user_plugin_dir.c_str(), true);
- }
- else
- {
- const char *home_dir = getenv("HOME");
- if (home_dir && home_dir[0])
- {
- std::string user_plugin_dir (home_dir);
- user_plugin_dir += "/.local/share/lldb";
- lldb_file_spec.SetFile (user_plugin_dir.c_str(), true);
- }
- }
-
- if (lldb_file_spec.Exists())
- g_lldb_user_plugin_dir.SetCString(lldb_file_spec.GetPath().c_str());
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", g_lldb_user_plugin_dir.GetCString());
- }
- file_spec.GetDirectory() = g_lldb_user_plugin_dir;
- return (bool)file_spec.GetDirectory();
-#endif
- // TODO: where would user LLDB plug-ins be located on other systems?
- return false;
- }
-
- case ePathTypeLLDBTempSystemDir:
- {
- static ConstString g_lldb_tmp_dir;
- if (!g_lldb_tmp_dir)
- {
- const char *tmpdir_cstr = getenv("TMPDIR");
- if (tmpdir_cstr == NULL)
- {
- tmpdir_cstr = getenv("TMP");
- if (tmpdir_cstr == NULL)
- tmpdir_cstr = getenv("TEMP");
- }
- if (tmpdir_cstr)
- {
- g_lldb_tmp_dir.SetCString(tmpdir_cstr);
- if (log)
- log->Printf("Host::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_lldb_tmp_dir.GetCString());
- }
- }
- file_spec.GetDirectory() = g_lldb_tmp_dir;
- return (bool)file_spec.GetDirectory();
- }
- }
-
- return false;
-}
-
-
-bool
-Host::GetHostname (std::string &s)
-{
- char hostname[PATH_MAX];
- hostname[sizeof(hostname) - 1] = '\0';
- if (::gethostname (hostname, sizeof(hostname) - 1) == 0)
- {
- struct hostent* h = ::gethostbyname (hostname);
- if (h)
- s.assign (h->h_name);
- else
- s.assign (hostname);
- return true;
- }
- return false;
-}
-
-#ifndef _WIN32
-
-const char *
-Host::GetUserName (uint32_t uid, std::string &user_name)
-{
- struct passwd user_info;
- struct passwd *user_info_ptr = &user_info;
- char user_buffer[PATH_MAX];
- size_t user_buffer_size = sizeof(user_buffer);
- if (::getpwuid_r (uid,
- &user_info,
- user_buffer,
- user_buffer_size,
- &user_info_ptr) == 0)
- {
- if (user_info_ptr)
- {
- user_name.assign (user_info_ptr->pw_name);
- return user_name.c_str();
- }
- }
- user_name.clear();
- return NULL;
-}
-
-const char *
-Host::GetGroupName (uint32_t gid, std::string &group_name)
-{
- char group_buffer[PATH_MAX];
- size_t group_buffer_size = sizeof(group_buffer);
- struct group group_info;
- struct group *group_info_ptr = &group_info;
- // Try the threadsafe version first
- if (::getgrgid_r (gid,
- &group_info,
- group_buffer,
- group_buffer_size,
- &group_info_ptr) == 0)
- {
- if (group_info_ptr)
- {
- group_name.assign (group_info_ptr->gr_name);
- return group_name.c_str();
- }
- }
- else
- {
- // The threadsafe version isn't currently working
- // for me on darwin, but the non-threadsafe version
- // is, so I am calling it below.
- group_info_ptr = ::getgrgid (gid);
- if (group_info_ptr)
- {
- group_name.assign (group_info_ptr->gr_name);
- return group_name.c_str();
- }
- }
- group_name.clear();
- return NULL;
-}
-
-uint32_t
-Host::GetUserID ()
-{
- return getuid();
-}
-
-uint32_t
-Host::GetGroupID ()
-{
- return getgid();
-}
-
-uint32_t
-Host::GetEffectiveUserID ()
-{
- return geteuid();
-}
-
-uint32_t
-Host::GetEffectiveGroupID ()
-{
- return getegid();
-}
-
-#endif
-
-#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) // see macosx/Host.mm
-bool
-Host::GetOSBuildString (std::string &s)
-{
- s.clear();
- return false;
-}
-
-bool
-Host::GetOSKernelDescription (std::string &s)
-{
- s.clear();
- return false;
-}
-#endif
-
-#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined(__linux__)
-uint32_t
-Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
-{
- process_infos.Clear();
- return process_infos.GetSize();
-}
-
-bool
-Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
-{
- process_info.Clear();
- return false;
-}
-#endif
-
#if !defined(__linux__)
bool
Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach)
@@ -1447,7 +709,7 @@ Host::GetDummyTarget (lldb_private::Debugger &debugger)
{
ArchSpec arch(Target::GetDefaultArchitecture());
if (!arch.IsValid())
- arch = Host::GetArchitecture ();
+ arch = HostInfo::GetArchitecture();
Error err = debugger.GetTargetList().CreateTarget(debugger,
NULL,
arch.GetTriple().getTriple().c_str(),
@@ -1545,9 +807,9 @@ Host::RunShellCommand (const char *command,
// output of the command into this file. We will later read this file
// if all goes well and fill the data into "command_output_ptr"
FileSpec tmpdir_file_spec;
- if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
{
- tmpdir_file_spec.GetFilename().SetCString("lldb-shell-output.XXXXXX");
+ tmpdir_file_spec.AppendPathComponent("lldb-shell-output.XXXXXX");
strncpy(output_file_path_buffer, tmpdir_file_spec.GetPath().c_str(), sizeof(output_file_path_buffer));
}
else
@@ -1601,7 +863,7 @@ Host::RunShellCommand (const char *command,
{
error.SetErrorString("timed out waiting for shell command to complete");
- // Kill the process since it didn't complete withint the timeout specified
+ // Kill the process since it didn't complete within the timeout specified
Kill (pid, SIGKILL);
// Wait for the monitor callback to get the message
timeout_time = TimeValue::Now();
@@ -1651,7 +913,7 @@ Host::RunShellCommand (const char *command,
// LaunchProcessPosixSpawn for Apple, Linux, FreeBSD and other GLIBC
// systems
-#if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__)
+#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.
@@ -1682,7 +944,7 @@ Host::GetPosixspawnFlags (ProcessLaunchInfo &launch_info)
g_use_close_on_exec_flag = eLazyBoolNo;
uint32_t major, minor, update;
- if (Host::GetOSVersion(major, minor, update))
+ if (HostInfo::GetOSVersion(major, minor, update))
{
// Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or earlier
if (major > 10 || (major == 10 && minor > 7))
@@ -1757,8 +1019,8 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i
cpu_type_t cpu = arch_spec.GetMachOCPUType();
cpu_type_t sub = arch_spec.GetMachOCPUSubType();
if (cpu != 0 &&
- cpu != UINT32_MAX &&
- cpu != LLDB_INVALID_CPUTYPE &&
+ cpu != static_cast<cpu_type_t>(UINT32_MAX) &&
+ cpu != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE) &&
!(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try to set the CPU type or we will fail
{
size_t ocount = 0;
@@ -1840,13 +1102,10 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i
for (size_t i=0; i<num_file_actions; ++i)
{
- const ProcessLaunchInfo::FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i);
+ const FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i);
if (launch_file_action)
{
- if (!ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions,
- launch_file_action,
- log,
- error))
+ if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log, error))
return error;
}
}
@@ -1862,12 +1121,10 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i
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,
- &file_actions,
- &attr,
- argv,
- envp);
+ pid, exe_path, static_cast<void*>(&file_actions),
+ static_cast<void*>(&attr),
+ reinterpret_cast<const void*>(argv),
+ reinterpret_cast<const void*>(envp));
if (log)
{
for (int ii=0; argv[ii]; ++ii)
@@ -1889,11 +1146,9 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i
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,
- &attr,
- argv,
- envp);
+ pid, exe_path, static_cast<void*>(&attr),
+ reinterpret_cast<const void*>(argv),
+ reinterpret_cast<const void*>(envp));
if (log)
{
for (int ii=0; argv[ii]; ++ii)
@@ -1920,12 +1175,79 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i
return error;
}
+bool
+Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Error &error)
+{
+ if (info == NULL)
+ return false;
+
+ posix_spawn_file_actions_t *file_actions = reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions);
+
+ switch (info->GetAction())
+ {
+ case FileAction::eFileActionNone:
+ error.Clear();
+ break;
+
+ case FileAction::eFileActionClose:
+ if (info->GetFD() == -1)
+ error.SetErrorString("invalid fd for posix_spawn_file_actions_addclose(...)");
+ else
+ {
+ error.SetError(::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), eErrorTypePOSIX);
+ if (log && (error.Fail() || log))
+ error.PutToLog(log, "posix_spawn_file_actions_addclose (action=%p, fd=%i)",
+ static_cast<void *>(file_actions), info->GetFD());
+ }
+ break;
+
+ case FileAction::eFileActionDuplicate:
+ if (info->GetFD() == -1)
+ error.SetErrorString("invalid fd for posix_spawn_file_actions_adddup2(...)");
+ else if (info->GetActionArgument() == -1)
+ error.SetErrorString("invalid duplicate fd for posix_spawn_file_actions_adddup2(...)");
+ else
+ {
+ error.SetError(
+ ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), info->GetActionArgument()),
+ eErrorTypePOSIX);
+ if (log && (error.Fail() || log))
+ error.PutToLog(log, "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)",
+ static_cast<void *>(file_actions), info->GetFD(), info->GetActionArgument());
+ }
+ break;
+
+ case FileAction::eFileActionOpen:
+ if (info->GetFD() == -1)
+ error.SetErrorString("invalid fd in posix_spawn_file_actions_addopen(...)");
+ else
+ {
+ int oflag = info->GetActionArgument();
+
+ mode_t mode = 0;
+
+ if (oflag & O_CREAT)
+ mode = 0640;
+
+ error.SetError(
+ ::posix_spawn_file_actions_addopen(file_actions, info->GetFD(), info->GetPath(), oflag, mode),
+ eErrorTypePOSIX);
+ if (error.Fail() || log)
+ error.PutToLog(log,
+ "posix_spawn_file_actions_addopen (action=%p, fd=%i, path='%s', oflag=%i, mode=%i)",
+ static_cast<void *>(file_actions), info->GetFD(), info->GetPath(), oflag, mode);
+ }
+ break;
+ }
+ return error.Success();
+}
+
#endif // LaunchProcedssPosixSpawn: Apple, Linux, FreeBSD and other GLIBC systems
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__)
-// The functions below implement process launching via posix_spawn() for Linux
-// and FreeBSD.
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || defined(__NetBSD__)
+// The functions below implement process launching via posix_spawn() for Linux,
+// FreeBSD and NetBSD.
Error
Host::LaunchProcess (ProcessLaunchInfo &launch_info)
@@ -2005,58 +1327,10 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info)
return error;
}
-#endif // defined(__linux__) or defined(__FreeBSD__)
+#endif // defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
#ifndef _WIN32
-size_t
-Host::GetPageSize()
-{
- return ::getpagesize();
-}
-
-uint32_t
-Host::GetNumberCPUS ()
-{
- static uint32_t g_num_cores = UINT32_MAX;
- if (g_num_cores == UINT32_MAX)
- {
-#if defined(__APPLE__) or defined (__linux__) or defined (__FreeBSD__) or defined (__FreeBSD_kernel__)
-
- g_num_cores = ::sysconf(_SC_NPROCESSORS_ONLN);
-
-#else
-
- // Assume POSIX support if a host specific case has not been supplied above
- g_num_cores = 0;
- int num_cores = 0;
- size_t num_cores_len = sizeof(num_cores);
-#ifdef HW_AVAILCPU
- int mib[] = { CTL_HW, HW_AVAILCPU };
-#else
- int mib[] = { CTL_HW, HW_NCPU };
-#endif
-
- /* get the number of CPUs from the system */
- if (sysctl(mib, sizeof(mib)/sizeof(int), &num_cores, &num_cores_len, NULL, 0) == 0 && (num_cores > 0))
- {
- g_num_cores = num_cores;
- }
- else
- {
- mib[1] = HW_NCPU;
- num_cores_len = sizeof(num_cores);
- if (sysctl(mib, sizeof(mib)/sizeof(int), &num_cores, &num_cores_len, NULL, 0) == 0 && (num_cores > 0))
- {
- if (num_cores > 0)
- g_num_cores = num_cores;
- }
- }
-#endif
- }
- return g_num_cores;
-}
-
void
Host::Kill(lldb::pid_t pid, int signo)
{
@@ -2090,319 +1364,13 @@ Host::LaunchApplication (const FileSpec &app_file_spec)
#endif
+#if !defined (__linux__) && !defined (__FreeBSD__) && !defined (__NetBSD__)
-#ifdef LLDB_DISABLE_POSIX
-
-Error
-Host::MakeDirectory (const char* path, uint32_t mode)
-{
- Error error;
- error.SetErrorStringWithFormat("%s in not implemented on this host", __PRETTY_FUNCTION__);
- return error;
-}
-
-Error
-Host::GetFilePermissions (const char* path, uint32_t &file_permissions)
-{
- Error error;
- error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
- return error;
-}
-
-Error
-Host::SetFilePermissions (const char* path, uint32_t file_permissions)
-{
- Error error;
- error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
- return error;
-}
-
-Error
-Host::Symlink (const char *src, const char *dst)
-{
- Error error;
- error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
- return error;
-}
-
-Error
-Host::Readlink (const char *path, char *buf, size_t buf_len)
-{
- Error error;
- error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
- return error;
-}
-
-Error
-Host::Unlink (const char *path)
-{
- Error error;
- error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
- return error;
-}
-
-#else
-
-Error
-Host::MakeDirectory (const char* path, uint32_t file_permissions)
-{
- Error error;
- if (path && path[0])
- {
- if (::mkdir(path, file_permissions) != 0)
- {
- error.SetErrorToErrno();
- switch (error.GetError())
- {
- case ENOENT:
- {
- // Parent directory doesn't exist, so lets make it if we can
- FileSpec spec(path, false);
- if (spec.GetDirectory() && spec.GetFilename())
- {
- // Make the parent directory and try again
- Error error2 = Host::MakeDirectory(spec.GetDirectory().GetCString(), file_permissions);
- if (error2.Success())
- {
- // Try and make the directory again now that the parent directory was made successfully
- if (::mkdir(path, file_permissions) == 0)
- error.Clear();
- else
- error.SetErrorToErrno();
- }
- }
- }
- break;
- case EEXIST:
- {
- FileSpec path_spec(path, false);
- if (path_spec.IsDirectory())
- error.Clear(); // It is a directory and it already exists
- }
- break;
- }
- }
- }
- else
- {
- error.SetErrorString("empty path");
- }
- return error;
-}
-
-Error
-Host::GetFilePermissions (const char* path, uint32_t &file_permissions)
-{
- Error error;
- struct stat file_stats;
- if (::stat (path, &file_stats) == 0)
- {
- // The bits in "st_mode" currently match the definitions
- // for the file mode bits in unix.
- file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
- }
- else
- {
- error.SetErrorToErrno();
- }
- return error;
-}
-
-Error
-Host::SetFilePermissions (const char* path, uint32_t file_permissions)
-{
- Error error;
- if (::chmod(path, file_permissions) != 0)
- error.SetErrorToErrno();
- return error;
-}
-
-Error
-Host::Symlink (const char *src, const char *dst)
-{
- Error error;
- if (::symlink(dst, src) == -1)
- error.SetErrorToErrno();
- return error;
-}
-
-Error
-Host::Unlink (const char *path)
-{
- Error error;
- if (::unlink(path) == -1)
- error.SetErrorToErrno();
- return error;
-}
-
-Error
-Host::Readlink (const char *path, char *buf, size_t buf_len)
-{
- Error error;
- ssize_t count = ::readlink(path, buf, buf_len);
- if (count < 0)
- error.SetErrorToErrno();
- else if (count < (buf_len-1))
- buf[count] = '\0'; // Success
- else
- error.SetErrorString("'buf' buffer is too small to contain link contents");
- return error;
-}
-
-
-#endif
-
-typedef std::map<lldb::user_id_t, lldb::FileSP> FDToFileMap;
-FDToFileMap& GetFDToFileMap()
-{
- static FDToFileMap g_fd2filemap;
- return g_fd2filemap;
-}
-
-lldb::user_id_t
-Host::OpenFile (const FileSpec& file_spec,
- uint32_t flags,
- uint32_t mode,
- Error &error)
+const lldb_private::UnixSignalsSP&
+Host::GetUnixSignals ()
{
- std::string path (file_spec.GetPath());
- if (path.empty())
- {
- error.SetErrorString("empty path");
- return UINT64_MAX;
- }
- FileSP file_sp(new File());
- error = file_sp->Open(path.c_str(),flags,mode);
- if (file_sp->IsValid() == false)
- return UINT64_MAX;
- lldb::user_id_t fd = file_sp->GetDescriptor();
- GetFDToFileMap()[fd] = file_sp;
- return fd;
+ static UnixSignalsSP s_unix_signals_sp (new UnixSignals ());
+ return s_unix_signals_sp;
}
-bool
-Host::CloseFile (lldb::user_id_t fd, Error &error)
-{
- if (fd == UINT64_MAX)
- {
- error.SetErrorString ("invalid file descriptor");
- return false;
- }
- FDToFileMap& file_map = GetFDToFileMap();
- FDToFileMap::iterator pos = file_map.find(fd);
- if (pos == file_map.end())
- {
- error.SetErrorStringWithFormat ("invalid host file descriptor %" PRIu64, fd);
- return false;
- }
- FileSP file_sp = pos->second;
- if (!file_sp)
- {
- error.SetErrorString ("invalid host backing file");
- return false;
- }
- error = file_sp->Close();
- file_map.erase(pos);
- return error.Success();
-}
-
-uint64_t
-Host::WriteFile (lldb::user_id_t fd, uint64_t offset, const void* src, uint64_t src_len, Error &error)
-{
- if (fd == UINT64_MAX)
- {
- error.SetErrorString ("invalid file descriptor");
- return UINT64_MAX;
- }
- FDToFileMap& file_map = GetFDToFileMap();
- FDToFileMap::iterator pos = file_map.find(fd);
- if (pos == file_map.end())
- {
- error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64 , fd);
- return false;
- }
- FileSP file_sp = pos->second;
- if (!file_sp)
- {
- error.SetErrorString ("invalid host backing file");
- return UINT64_MAX;
- }
- if (file_sp->SeekFromStart(offset, &error) != offset || error.Fail())
- return UINT64_MAX;
- size_t bytes_written = src_len;
- error = file_sp->Write(src, bytes_written);
- if (error.Fail())
- return UINT64_MAX;
- return bytes_written;
-}
-
-uint64_t
-Host::ReadFile (lldb::user_id_t fd, uint64_t offset, void* dst, uint64_t dst_len, Error &error)
-{
- if (fd == UINT64_MAX)
- {
- error.SetErrorString ("invalid file descriptor");
- return UINT64_MAX;
- }
- FDToFileMap& file_map = GetFDToFileMap();
- FDToFileMap::iterator pos = file_map.find(fd);
- if (pos == file_map.end())
- {
- error.SetErrorStringWithFormat ("invalid host file descriptor %" PRIu64, fd);
- return false;
- }
- FileSP file_sp = pos->second;
- if (!file_sp)
- {
- error.SetErrorString ("invalid host backing file");
- return UINT64_MAX;
- }
- if (file_sp->SeekFromStart(offset, &error) != offset || error.Fail())
- return UINT64_MAX;
- size_t bytes_read = dst_len;
- error = file_sp->Read(dst ,bytes_read);
- if (error.Fail())
- return UINT64_MAX;
- return bytes_read;
-}
-
-lldb::user_id_t
-Host::GetFileSize (const FileSpec& file_spec)
-{
- return file_spec.GetByteSize();
-}
-
-bool
-Host::GetFileExists (const FileSpec& file_spec)
-{
- return file_spec.Exists();
-}
-
-bool
-Host::CalculateMD5 (const FileSpec& file_spec,
- uint64_t &low,
- uint64_t &high)
-{
-#if defined (__APPLE__)
- StreamString md5_cmd_line;
- md5_cmd_line.Printf("md5 -q '%s'", file_spec.GetPath().c_str());
- std::string hash_string;
- Error err = Host::RunShellCommand(md5_cmd_line.GetData(), NULL, NULL, NULL, &hash_string, 60);
- if (err.Fail())
- return false;
- // a correctly formed MD5 is 16-bytes, that is 32 hex digits
- // if the output is any other length it is probably wrong
- if (hash_string.size() != 32)
- return false;
- std::string part1(hash_string,0,16);
- std::string part2(hash_string,16);
- const char* part1_cstr = part1.c_str();
- const char* part2_cstr = part2.c_str();
- high = ::strtoull(part1_cstr, NULL, 16);
- low = ::strtoull(part2_cstr, NULL, 16);
- return true;
-#else
- // your own MD5 implementation here
- return false;
#endif
-}
diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp
new file mode 100644
index 000000000000..4eb43bfaf6ff
--- /dev/null
+++ b/source/Host/common/HostInfoBase.cpp
@@ -0,0 +1,318 @@
+//===-- HostInfoBase.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/Config.h"
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/HostInfoBase.h"
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Host.h"
+
+#include <thread>
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace
+{
+void
+CleanupProcessSpecificLLDBTempDir()
+{
+ // Get the process specific LLDB temporary directory and delete it.
+ FileSpec tmpdir_file_spec;
+ if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
+ return;
+
+ // Remove the LLDB temporary directory if we have one. Set "recurse" to
+ // true to all files that were created for the LLDB process can be cleaned up.
+ FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true);
+}
+
+struct HostInfoBaseFields
+{
+ uint32_t m_number_cpus;
+ std::string m_vendor_string;
+ std::string m_os_string;
+ std::string m_host_triple;
+
+ ArchSpec m_host_arch_32;
+ ArchSpec m_host_arch_64;
+
+ FileSpec m_lldb_so_dir;
+ FileSpec m_lldb_support_exe_dir;
+ FileSpec m_lldb_headers_dir;
+ FileSpec m_lldb_python_dir;
+ FileSpec m_lldb_system_plugin_dir;
+ FileSpec m_lldb_user_plugin_dir;
+ FileSpec m_lldb_tmp_dir;
+};
+
+HostInfoBaseFields *g_fields = nullptr;
+}
+
+#define COMPUTE_LLDB_PATH(compute_function, member_var) \
+ { \
+ static bool is_initialized = false; \
+ static bool success = false; \
+ if (!is_initialized) \
+ { \
+ is_initialized = true; \
+ success = HostInfo::compute_function(member_var); \
+ } \
+ if (success) \
+ result = &member_var; \
+ }
+
+void
+HostInfoBase::Initialize()
+{
+ g_fields = new HostInfoBaseFields();
+}
+
+uint32_t
+HostInfoBase::GetNumberCPUS()
+{
+ static bool is_initialized = false;
+ if (!is_initialized)
+ {
+ g_fields->m_number_cpus = std::thread::hardware_concurrency();
+ is_initialized = true;
+ }
+
+ return g_fields->m_number_cpus;
+}
+
+llvm::StringRef
+HostInfoBase::GetVendorString()
+{
+ static bool is_initialized = false;
+ if (!is_initialized)
+ {
+ const ArchSpec &host_arch = HostInfo::GetArchitecture();
+ const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName();
+ g_fields->m_vendor_string.assign(str_ref.begin(), str_ref.end());
+ is_initialized = true;
+ }
+ return g_fields->m_vendor_string;
+}
+
+llvm::StringRef
+HostInfoBase::GetOSString()
+{
+ static bool is_initialized = false;
+ if (!is_initialized)
+ {
+ const ArchSpec &host_arch = HostInfo::GetArchitecture();
+ const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName();
+ g_fields->m_os_string.assign(str_ref.begin(), str_ref.end());
+ is_initialized = true;
+ }
+ return g_fields->m_os_string;
+}
+
+llvm::StringRef
+HostInfoBase::GetTargetTriple()
+{
+ static bool is_initialized = false;
+ if (!is_initialized)
+ {
+ const ArchSpec &host_arch = HostInfo::GetArchitecture();
+ g_fields->m_host_triple = host_arch.GetTriple().getTriple();
+ is_initialized = true;
+ }
+ return g_fields->m_host_triple;
+}
+
+const ArchSpec &
+HostInfoBase::GetArchitecture(ArchitectureKind arch_kind)
+{
+ static bool is_initialized = false;
+ if (!is_initialized)
+ {
+ HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64);
+ is_initialized = true;
+ }
+
+ // If an explicit 32 or 64-bit architecture was requested, return that.
+ if (arch_kind == eArchKind32)
+ return g_fields->m_host_arch_32;
+ if (arch_kind == eArchKind64)
+ return g_fields->m_host_arch_64;
+
+ // Otherwise prefer the 64-bit architecture if it is valid.
+ return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 : g_fields->m_host_arch_32;
+}
+
+bool
+HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec)
+{
+ file_spec.Clear();
+
+#if defined(LLDB_DISABLE_PYTHON)
+ if (type == lldb::ePathTypePythonDir)
+ return false;
+#endif
+
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ FileSpec *result = nullptr;
+ switch (type)
+ {
+ case lldb::ePathTypeLLDBShlibDir:
+ COMPUTE_LLDB_PATH(ComputeSharedLibraryDirectory, g_fields->m_lldb_so_dir)
+ if (log)
+ log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str());
+ break;
+ case lldb::ePathTypeSupportExecutableDir:
+ COMPUTE_LLDB_PATH(ComputeSupportExeDirectory, g_fields->m_lldb_support_exe_dir)
+ if (log)
+ log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
+ g_fields->m_lldb_support_exe_dir.GetPath().c_str());
+ break;
+ case lldb::ePathTypeHeaderDir:
+ COMPUTE_LLDB_PATH(ComputeHeaderDirectory, g_fields->m_lldb_headers_dir)
+ if (log)
+ log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str());
+ break;
+ case lldb::ePathTypePythonDir:
+ COMPUTE_LLDB_PATH(ComputePythonDirectory, g_fields->m_lldb_python_dir)
+ if (log)
+ log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str());
+ break;
+ case lldb::ePathTypeLLDBSystemPlugins:
+ COMPUTE_LLDB_PATH(ComputeSystemPluginsDirectory, g_fields->m_lldb_system_plugin_dir)
+ if (log)
+ log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
+ g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
+ break;
+ case lldb::ePathTypeLLDBUserPlugins:
+ COMPUTE_LLDB_PATH(ComputeUserPluginsDirectory, g_fields->m_lldb_user_plugin_dir)
+ if (log)
+ log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
+ g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
+ break;
+ case lldb::ePathTypeLLDBTempSystemDir:
+ COMPUTE_LLDB_PATH(ComputeTempFileDirectory, g_fields->m_lldb_tmp_dir)
+ if (log)
+ log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str());
+ break;
+ }
+
+ if (!result)
+ return false;
+ file_spec = *result;
+ return true;
+}
+
+bool
+HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
+{
+ // To get paths related to LLDB we get the path to the executable that
+ // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
+ // on linux this is assumed to be the "lldb" main executable. If LLDB on
+ // linux is actually in a shared library (liblldb.so) then this function will
+ // need to be modified to "do the right thing".
+
+ FileSpec lldb_file_spec(
+ Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
+
+ // Remove the filename so that this FileSpec only represents the directory.
+ file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
+
+ return (bool)file_spec.GetDirectory();
+}
+
+bool
+HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec)
+{
+ return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
+}
+
+bool
+HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec)
+{
+ const char *tmpdir_cstr = getenv("TMPDIR");
+ if (tmpdir_cstr == NULL)
+ {
+ tmpdir_cstr = getenv("TMP");
+ if (tmpdir_cstr == NULL)
+ tmpdir_cstr = getenv("TEMP");
+ }
+ 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())
+ return false;
+
+ pid_tmpdir.Printf("/%" PRIu64, Host::GetCurrentProcessID());
+ if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().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());
+ return true;
+}
+
+bool
+HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec)
+{
+ // TODO(zturner): Figure out how to compute the header directory for all platforms.
+ return false;
+}
+
+bool
+HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec)
+{
+ // TODO(zturner): Figure out how to compute the system plugins directory for all platforms.
+ return false;
+}
+
+bool
+HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec)
+{
+ // TODO(zturner): Figure out how to compute the user plugins directory for all platforms.
+ return false;
+}
+
+void
+HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
+{
+ llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
+
+ arch_32.Clear();
+ arch_64.Clear();
+
+ switch (triple.getArch())
+ {
+ default:
+ arch_32.SetTriple(triple);
+ break;
+
+ case llvm::Triple::x86_64:
+ arch_64.SetTriple(triple);
+ arch_32.SetTriple(triple.get32BitArchVariant());
+ break;
+
+ case llvm::Triple::aarch64:
+ case llvm::Triple::mips64:
+ case llvm::Triple::sparcv9:
+ case llvm::Triple::ppc64:
+ arch_64.SetTriple(triple);
+ break;
+ }
+}
diff --git a/source/Host/common/IOObject.cpp b/source/Host/common/IOObject.cpp
new file mode 100644
index 000000000000..6f7de442be1d
--- /dev/null
+++ b/source/Host/common/IOObject.cpp
@@ -0,0 +1,14 @@
+//===-- IOObject.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/IOObject.h"
+
+using namespace lldb_private;
+
+const IOObject::WaitableHandle IOObject::kInvalidHandleValue = -1;
diff --git a/source/Host/common/Mutex.cpp b/source/Host/common/Mutex.cpp
index 4e0135535628..c26467fa0d79 100644
--- a/source/Host/common/Mutex.cpp
+++ b/source/Host/common/Mutex.cpp
@@ -242,9 +242,9 @@ Mutex::Mutex (Mutex::Type type) :
//----------------------------------------------------------------------
Mutex::~Mutex()
{
+#if ENABLE_MUTEX_ERROR_CHECKING
int err = ::pthread_mutex_destroy (&m_mutex);
assert(err == 0);
-#if ENABLE_MUTEX_ERROR_CHECKING
if (err == 0)
error_check_mutex (&m_mutex, eMutexActionDestroyed);
else
@@ -253,6 +253,8 @@ Mutex::~Mutex()
assert(err == 0);
}
memset (&m_mutex, '\xba', sizeof(m_mutex));
+#else
+ ::pthread_mutex_destroy (&m_mutex);
#endif
}
diff --git a/source/Host/common/NativeBreakpoint.cpp b/source/Host/common/NativeBreakpoint.cpp
new file mode 100644
index 000000000000..284d7d11d6ce
--- /dev/null
+++ b/source/Host/common/NativeBreakpoint.cpp
@@ -0,0 +1,116 @@
+//===-- NativeBreakpoint.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NativeBreakpoint.h"
+
+#include "lldb/lldb-defines.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+
+using namespace lldb_private;
+
+NativeBreakpoint::NativeBreakpoint (lldb::addr_t addr) :
+ m_addr (addr),
+ m_ref_count (1),
+ m_enabled (true)
+{
+ assert (addr != LLDB_INVALID_ADDRESS && "breakpoint set for invalid address");
+}
+
+NativeBreakpoint::~NativeBreakpoint ()
+{
+}
+
+void
+NativeBreakpoint::AddRef ()
+{
+ ++m_ref_count;
+
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " bumped up, new ref count %" PRIu32, __FUNCTION__, m_addr, m_ref_count);
+}
+
+int32_t
+NativeBreakpoint::DecRef ()
+{
+ --m_ref_count;
+
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " ref count decremented, new ref count %" PRIu32, __FUNCTION__, m_addr, m_ref_count);
+
+ return m_ref_count;
+}
+
+Error
+NativeBreakpoint::Enable ()
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+
+ if (m_enabled)
+ {
+ // We're already enabled. Just log and exit.
+ if (log)
+ log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " already enabled, ignoring.", __FUNCTION__, m_addr);
+ return Error ();
+ }
+
+ // Log and enable.
+ if (log)
+ log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " enabling...", __FUNCTION__, m_addr);
+
+ Error error = DoEnable ();
+ if (error.Success ())
+ {
+ m_enabled = true;
+ if (log)
+ log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable SUCCESS.", __FUNCTION__, m_addr);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable FAIL: %s", __FUNCTION__, m_addr, error.AsCString ());
+ }
+
+ return error;
+}
+
+Error
+NativeBreakpoint::Disable ()
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+
+ if (!m_enabled)
+ {
+ // We're already disabled. Just log and exit.
+ if (log)
+ log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " already disabled, ignoring.", __FUNCTION__, m_addr);
+ return Error ();
+ }
+
+ // Log and disable.
+ if (log)
+ log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " disabling...", __FUNCTION__, m_addr);
+
+ Error error = DoDisable ();
+ if (error.Success ())
+ {
+ m_enabled = false;
+ if (log)
+ log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable SUCCESS.", __FUNCTION__, m_addr);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable FAIL: %s", __FUNCTION__, m_addr, error.AsCString ());
+ }
+
+ return error;
+}
diff --git a/source/Host/common/NativeBreakpoint.h b/source/Host/common/NativeBreakpoint.h
new file mode 100644
index 000000000000..367003b94e35
--- /dev/null
+++ b/source/Host/common/NativeBreakpoint.h
@@ -0,0 +1,66 @@
+//===-- NativeBreakpoint.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_NativeBreakpoint_h_
+#define liblldb_NativeBreakpoint_h_
+
+#include "lldb/lldb-types.h"
+
+namespace lldb_private
+{
+ class NativeBreakpointList;
+
+ class NativeBreakpoint
+ {
+ friend class NativeBreakpointList;
+
+ public:
+ // The assumption is that derived breakpoints are enabled when created.
+ NativeBreakpoint (lldb::addr_t addr);
+
+ virtual
+ ~NativeBreakpoint ();
+
+ Error
+ Enable ();
+
+ Error
+ Disable ();
+
+ lldb::addr_t
+ GetAddress () const { return m_addr; }
+
+ bool
+ IsEnabled () const { return m_enabled; }
+
+ virtual bool
+ IsSoftwareBreakpoint () const = 0;
+
+ protected:
+ const lldb::addr_t m_addr;
+ int32_t m_ref_count;
+
+ virtual Error
+ DoEnable () = 0;
+
+ virtual Error
+ DoDisable () = 0;
+
+ private:
+ bool m_enabled;
+
+ // -----------------------------------------------------------
+ // interface for NativeBreakpointList
+ // -----------------------------------------------------------
+ void AddRef ();
+ int32_t DecRef ();
+ };
+}
+
+#endif // ifndef liblldb_NativeBreakpoint_h_
diff --git a/source/Host/common/NativeBreakpointList.cpp b/source/Host/common/NativeBreakpointList.cpp
new file mode 100644
index 000000000000..ecd0624bde09
--- /dev/null
+++ b/source/Host/common/NativeBreakpointList.cpp
@@ -0,0 +1,199 @@
+//===-- NativeBreakpointList.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NativeBreakpointList.h"
+
+#include "lldb/Core/Log.h"
+
+#include "NativeBreakpoint.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+NativeBreakpointList::NativeBreakpointList () :
+ m_mutex (Mutex::eMutexTypeRecursive)
+{
+}
+
+Error
+NativeBreakpointList::AddRef (lldb::addr_t addr, size_t size_hint, bool hardware, CreateBreakpointFunc create_func)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false");
+
+ Mutex::Locker locker (m_mutex);
+
+ // Check if the breakpoint is already set.
+ auto iter = m_breakpoints.find (addr);
+ if (iter != m_breakpoints.end ())
+ {
+ // Yes - bump up ref count.
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- already enabled, upping ref count", __FUNCTION__, addr);
+
+ iter->second->AddRef ();
+ return Error ();
+ }
+
+ // Create a new breakpoint using the given create func.
+ if (log)
+ log->Printf ("NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false");
+
+ NativeBreakpointSP breakpoint_sp;
+ Error error = create_func (addr, size_hint, hardware, breakpoint_sp);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s -- FAILED: %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false", error.AsCString ());
+ return error;
+ }
+
+ // Remember the breakpoint.
+ assert (breakpoint_sp && "NativeBreakpoint create function succeeded but returned NULL breakpoint");
+ m_breakpoints.insert (BreakpointMap::value_type (addr, breakpoint_sp));
+
+ return error;
+}
+
+Error
+NativeBreakpointList::DecRef (lldb::addr_t addr)
+{
+ Error error;
+
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
+
+ Mutex::Locker locker (m_mutex);
+
+ // Check if the breakpoint is already set.
+ auto iter = m_breakpoints.find (addr);
+ if (iter == m_breakpoints.end ())
+ {
+ // Not found!
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr);
+ error.SetErrorString ("breakpoint not found");
+ return error;
+ }
+
+ // Decrement ref count.
+ const int32_t new_ref_count = iter->second->DecRef ();
+ assert (new_ref_count >= 0 && "NativeBreakpoint ref count went negative");
+
+ if (new_ref_count > 0)
+ {
+ // Still references to this breakpoint. Leave it alone.
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- new breakpoint ref count %" PRIu32, __FUNCTION__, addr, new_ref_count);
+ return error;
+ }
+
+ // Breakpoint has no more references. Disable it if it's not
+ // already disabled.
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removing due to no remaining references", __FUNCTION__, addr);
+
+ // If it's enabled, we need to disable it.
+ if (iter->second->IsEnabled ())
+ {
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- currently enabled, now disabling", __FUNCTION__, addr);
+ error = iter->second->Disable ();
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removal FAILED: %s", __FUNCTION__, addr, error.AsCString ());
+ // Continue since we still want to take it out of the breakpoint list.
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- already disabled, nothing to do", __FUNCTION__, addr);
+ }
+
+ // Take the breakpoint out of the list.
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removed from breakpoint map", __FUNCTION__, addr);
+
+ m_breakpoints.erase (iter);
+ return error;
+}
+
+Error
+NativeBreakpointList::EnableBreakpoint (lldb::addr_t addr)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
+
+ Mutex::Locker locker (m_mutex);
+
+ // Ensure we have said breakpoint.
+ auto iter = m_breakpoints.find (addr);
+ if (iter == m_breakpoints.end ())
+ {
+ // Not found!
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr);
+ return Error ("breakpoint not found");
+ }
+
+ // Enable it.
+ return iter->second->Enable ();
+}
+
+Error
+NativeBreakpointList::DisableBreakpoint (lldb::addr_t addr)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
+
+ Mutex::Locker locker (m_mutex);
+
+ // Ensure we have said breakpoint.
+ auto iter = m_breakpoints.find (addr);
+ if (iter == m_breakpoints.end ())
+ {
+ // Not found!
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr);
+ return Error ("breakpoint not found");
+ }
+
+ // Disable it.
+ return iter->second->Disable ();
+}
+
+Error
+NativeBreakpointList::GetBreakpoint (lldb::addr_t addr, NativeBreakpointSP &breakpoint_sp)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
+
+ Mutex::Locker locker (m_mutex);
+
+ // Ensure we have said breakpoint.
+ auto iter = m_breakpoints.find (addr);
+ if (iter == m_breakpoints.end ())
+ {
+ // Not found!
+ breakpoint_sp.reset ();
+ return Error ("breakpoint not found");
+ }
+
+ // Disable it.
+ breakpoint_sp = iter->second;
+ return Error ();
+}
+
diff --git a/source/Host/common/NativeBreakpointList.h b/source/Host/common/NativeBreakpointList.h
new file mode 100644
index 000000000000..51617330d075
--- /dev/null
+++ b/source/Host/common/NativeBreakpointList.h
@@ -0,0 +1,53 @@
+//===-- NativeBreakpointList.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_NativeBreakpointList_h_
+#define liblldb_NativeBreakpointList_h_
+
+#include "lldb/lldb-private-forward.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Host/Mutex.h"
+// #include "lldb/Host/NativeBreakpoint.h"
+
+#include <functional>
+#include <map>
+
+namespace lldb_private
+{
+ class NativeBreakpointList
+ {
+ public:
+ typedef std::function<Error (lldb::addr_t addr, size_t size_hint, bool hardware, NativeBreakpointSP &breakpoint_sp)> CreateBreakpointFunc;
+
+ NativeBreakpointList ();
+
+ Error
+ AddRef (lldb::addr_t addr, size_t size_hint, bool hardware, CreateBreakpointFunc create_func);
+
+ Error
+ DecRef (lldb::addr_t addr);
+
+ Error
+ EnableBreakpoint (lldb::addr_t addr);
+
+ Error
+ DisableBreakpoint (lldb::addr_t addr);
+
+ Error
+ GetBreakpoint (lldb::addr_t addr, NativeBreakpointSP &breakpoint_sp);
+
+ private:
+ typedef std::map<lldb::addr_t, NativeBreakpointSP> BreakpointMap;
+
+ Mutex m_mutex;
+ BreakpointMap m_breakpoints;
+ };
+}
+
+#endif // ifndef liblldb_NativeBreakpointList_h_
diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp
new file mode 100644
index 000000000000..b7a77266c58c
--- /dev/null
+++ b/source/Host/common/NativeProcessProtocol.cpp
@@ -0,0 +1,412 @@
+//===-- NativeProcessProtocol.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NativeProcessProtocol.h"
+
+#include "lldb/lldb-enumerations.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/State.h"
+#include "lldb/Target/NativeRegisterContext.h"
+
+#include "NativeThreadProtocol.h"
+#include "SoftwareBreakpoint.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// -----------------------------------------------------------------------------
+// NativeProcessProtocol Members
+// -----------------------------------------------------------------------------
+
+NativeProcessProtocol::NativeProcessProtocol (lldb::pid_t pid) :
+ m_pid (pid),
+ m_threads (),
+ m_current_thread_id (LLDB_INVALID_THREAD_ID),
+ m_threads_mutex (Mutex::eMutexTypeRecursive),
+ m_state (lldb::eStateInvalid),
+ m_state_mutex (Mutex::eMutexTypeRecursive),
+ m_exit_type (eExitTypeInvalid),
+ m_exit_status (0),
+ m_exit_description (),
+ m_delegates_mutex (Mutex::eMutexTypeRecursive),
+ m_delegates (),
+ m_breakpoint_list (),
+ m_terminal_fd (-1),
+ m_stop_id (0)
+{
+}
+
+lldb_private::Error
+NativeProcessProtocol::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info)
+{
+ // Default: not implemented.
+ return Error ("not implemented");
+}
+
+bool
+NativeProcessProtocol::GetExitStatus (ExitType *exit_type, int *status, std::string &exit_description)
+{
+ if (m_state == lldb::eStateExited)
+ {
+ *exit_type = m_exit_type;
+ *status = m_exit_status;
+ exit_description = m_exit_description;
+ return true;
+ }
+
+ *status = 0;
+ return false;
+}
+
+bool
+NativeProcessProtocol::SetExitStatus (ExitType exit_type, int status, const char *exit_description, bool bNotifyStateChange)
+{
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf ("NativeProcessProtocol::%s(%d, %d, %s, %s) called",
+ __FUNCTION__,
+ exit_type,
+ status,
+ exit_description ? exit_description : "nullptr",
+ bNotifyStateChange ? "true" : "false");
+
+ // Exit status already set
+ if (m_state == lldb::eStateExited)
+ {
+ if (log)
+ log->Printf ("NativeProcessProtocol::%s exit status already set to %d, ignoring new set to %d", __FUNCTION__, m_exit_status, status);
+ return false;
+ }
+
+ m_state = lldb::eStateExited;
+
+ m_exit_type = exit_type;
+ m_exit_status = status;
+ if (exit_description && exit_description[0])
+ m_exit_description = exit_description;
+ else
+ m_exit_description.clear();
+
+ if (bNotifyStateChange)
+ SynchronouslyNotifyProcessStateChanged (lldb::eStateExited);
+
+ return true;
+}
+
+NativeThreadProtocolSP
+NativeProcessProtocol::GetThreadAtIndex (uint32_t idx)
+{
+ Mutex::Locker locker (m_threads_mutex);
+ if (idx < m_threads.size ())
+ return m_threads[idx];
+ return NativeThreadProtocolSP ();
+}
+
+NativeThreadProtocolSP
+NativeProcessProtocol::GetThreadByID (lldb::tid_t tid)
+{
+ Mutex::Locker locker (m_threads_mutex);
+ for (auto thread_sp : m_threads)
+ {
+ if (thread_sp->GetID() == tid)
+ return thread_sp;
+ }
+ return NativeThreadProtocolSP ();
+}
+
+bool
+NativeProcessProtocol::IsAlive () const
+{
+ return m_state != eStateDetached
+ && m_state != eStateExited
+ && m_state != eStateInvalid
+ && m_state != eStateUnloaded;
+}
+
+bool
+NativeProcessProtocol::GetByteOrder (lldb::ByteOrder &byte_order) const
+{
+ ArchSpec process_arch;
+ if (!GetArchitecture (process_arch))
+ return false;
+ byte_order = process_arch.GetByteOrder ();
+ return true;
+}
+
+uint32_t
+NativeProcessProtocol::GetMaxWatchpoints () const
+{
+ // This default implementation will return the number of
+ // *hardware* breakpoints available. MacOSX and other OS
+ // implementations that support software breakpoints will want to
+ // override this correctly for their implementation.
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+
+ // get any thread
+ NativeThreadProtocolSP thread_sp (const_cast<NativeProcessProtocol*> (this)->GetThreadAtIndex (0));
+ if (!thread_sp)
+ {
+ if (log)
+ log->Warning ("NativeProcessProtocol::%s (): failed to find a thread to grab a NativeRegisterContext!", __FUNCTION__);
+ return 0;
+ }
+
+ NativeRegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext ());
+ if (!reg_ctx_sp)
+ {
+ if (log)
+ log->Warning ("NativeProcessProtocol::%s (): failed to get a RegisterContextNativeProcess from the first thread!", __FUNCTION__);
+ return 0;
+ }
+
+ return reg_ctx_sp->NumSupportedHardwareWatchpoints ();
+}
+
+Error
+NativeProcessProtocol::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
+{
+ // This default implementation assumes setting the watchpoint for
+ // the process will require setting the watchpoint for each of the
+ // threads. Furthermore, it will track watchpoints set for the
+ // process and will add them to each thread that is attached to
+ // via the (FIXME implement) OnThreadAttached () method.
+
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+
+ // FIXME save the watchpoint on the set of process watchpoint vars
+ // so we can add them to a thread each time a new thread is registered.
+
+ // Update the thread list
+ UpdateThreads ();
+
+ // Keep track of the threads we successfully set the watchpoint
+ // for. If one of the thread watchpoint setting operations fails,
+ // back off and remove the watchpoint for all the threads that
+ // were successfully set so we get back to a consistent state.
+ std::vector<NativeThreadProtocolSP> watchpoint_established_threads;
+
+ // Tell each thread to set a watchpoint. In the event that
+ // hardware watchpoints are requested but the SetWatchpoint fails,
+ // try to set a software watchpoint as a fallback. It's
+ // conceivable that if there are more threads than hardware
+ // watchpoints available, some of the threads will fail to set
+ // hardware watchpoints while software ones may be available.
+ Mutex::Locker locker (m_threads_mutex);
+ for (auto thread_sp : m_threads)
+ {
+ assert (thread_sp && "thread list should not have a NULL thread!");
+ if (!thread_sp)
+ continue;
+
+ Error thread_error = thread_sp->SetWatchpoint (addr, size, watch_flags, hardware);
+ if (thread_error.Fail () && hardware)
+ {
+ // Try software watchpoints since we failed on hardware watchpoint setting
+ // and we may have just run out of hardware watchpoints.
+ thread_error = thread_sp->SetWatchpoint (addr, size, watch_flags, false);
+ if (thread_error.Success ())
+ {
+ if (log)
+ log->Warning ("hardware watchpoint requested but software watchpoint set");
+ }
+ }
+
+ if (thread_error.Success ())
+ {
+ // Remember that we set this watchpoint successfully in
+ // case we need to clear it later.
+ watchpoint_established_threads.push_back (thread_sp);
+ }
+ else
+ {
+ // Unset the watchpoint for each thread we successfully
+ // set so that we get back to a consistent state of "not
+ // set" for the watchpoint.
+ for (auto unwatch_thread_sp : watchpoint_established_threads)
+ {
+ Error remove_error = unwatch_thread_sp->RemoveWatchpoint (addr);
+ if (remove_error.Fail () && log)
+ {
+ log->Warning ("NativeProcessProtocol::%s (): RemoveWatchpoint failed for pid=%" PRIu64 ", tid=%" PRIu64 ": %s",
+ __FUNCTION__, GetID (), unwatch_thread_sp->GetID (), remove_error.AsCString ());
+ }
+ }
+
+ return thread_error;
+ }
+ }
+ return Error ();
+}
+
+Error
+NativeProcessProtocol::RemoveWatchpoint (lldb::addr_t addr)
+{
+ // FIXME remove the watchpoint on the set of process watchpoint vars
+ // so we can add them to a thread each time a new thread is registered.
+
+ // Update the thread list
+ UpdateThreads ();
+
+ Error overall_error;
+
+ Mutex::Locker locker (m_threads_mutex);
+ for (auto thread_sp : m_threads)
+ {
+ assert (thread_sp && "thread list should not have a NULL thread!");
+ if (!thread_sp)
+ continue;
+
+ const Error thread_error = thread_sp->RemoveWatchpoint (addr);
+ if (thread_error.Fail ())
+ {
+ // Keep track of the first thread error if any threads
+ // fail. We want to try to remove the watchpoint from
+ // every thread, though, even if one or more have errors.
+ if (!overall_error.Fail ())
+ overall_error = thread_error;
+ }
+ }
+ return overall_error;
+}
+
+bool
+NativeProcessProtocol::RegisterNativeDelegate (NativeDelegate &native_delegate)
+{
+ Mutex::Locker locker (m_delegates_mutex);
+ if (std::find (m_delegates.begin (), m_delegates.end (), &native_delegate) != m_delegates.end ())
+ return false;
+
+ m_delegates.push_back (&native_delegate);
+ native_delegate.InitializeDelegate (this);
+ return true;
+}
+
+bool
+NativeProcessProtocol::UnregisterNativeDelegate (NativeDelegate &native_delegate)
+{
+ Mutex::Locker locker (m_delegates_mutex);
+
+ const auto initial_size = m_delegates.size ();
+ m_delegates.erase (remove (m_delegates.begin (), m_delegates.end (), &native_delegate), m_delegates.end ());
+
+ // We removed the delegate if the count of delegates shrank after
+ // removing all copies of the given native_delegate from the vector.
+ return m_delegates.size () < initial_size;
+}
+
+void
+NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged (lldb::StateType state)
+{
+ Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+
+ Mutex::Locker locker (m_delegates_mutex);
+ for (auto native_delegate: m_delegates)
+ native_delegate->ProcessStateChanged (this, state);
+
+ if (log)
+ {
+ if (!m_delegates.empty ())
+ {
+ log->Printf ("NativeProcessProtocol::%s: sent state notification [%s] from process %" PRIu64,
+ __FUNCTION__, lldb_private::StateAsCString (state), GetID ());
+ }
+ else
+ {
+ log->Printf ("NativeProcessProtocol::%s: would send state notification [%s] from process %" PRIu64 ", but no delegates",
+ __FUNCTION__, lldb_private::StateAsCString (state), GetID ());
+ }
+ }
+}
+
+void
+NativeProcessProtocol::NotifyDidExec ()
+{
+ Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf ("NativeProcessProtocol::%s - preparing to call delegates", __FUNCTION__);
+
+ {
+ Mutex::Locker locker (m_delegates_mutex);
+ for (auto native_delegate: m_delegates)
+ native_delegate->DidExec (this);
+ }
+}
+
+
+Error
+NativeProcessProtocol::SetSoftwareBreakpoint (lldb::addr_t addr, uint32_t size_hint)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("NativeProcessProtocol::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
+
+ return m_breakpoint_list.AddRef (addr, size_hint, false,
+ [this] (lldb::addr_t addr, size_t size_hint, bool /* hardware */, NativeBreakpointSP &breakpoint_sp)->Error
+ { return SoftwareBreakpoint::CreateSoftwareBreakpoint (*this, addr, size_hint, breakpoint_sp); });
+}
+
+Error
+NativeProcessProtocol::RemoveBreakpoint (lldb::addr_t addr)
+{
+ return m_breakpoint_list.DecRef (addr);
+}
+
+Error
+NativeProcessProtocol::EnableBreakpoint (lldb::addr_t addr)
+{
+ return m_breakpoint_list.EnableBreakpoint (addr);
+}
+
+Error
+NativeProcessProtocol::DisableBreakpoint (lldb::addr_t addr)
+{
+ return m_breakpoint_list.DisableBreakpoint (addr);
+}
+
+lldb::StateType
+NativeProcessProtocol::GetState () const
+{
+ Mutex::Locker locker (m_state_mutex);
+ return m_state;
+}
+
+void
+NativeProcessProtocol::SetState (lldb::StateType state, bool notify_delegates)
+{
+ Mutex::Locker locker (m_state_mutex);
+ m_state = state;
+
+ if (StateIsStoppedState (state, false))
+ {
+ ++m_stop_id;
+
+ // Give process a chance to do any stop id bump processing, such as
+ // clearing cached data that is invalidated each time the process runs.
+ // Note if/when we support some threads running, we'll end up needing
+ // to manage this per thread and per process.
+ DoStopIDBumped (m_stop_id);
+ }
+
+ // Optionally notify delegates of the state change.
+ if (notify_delegates)
+ SynchronouslyNotifyProcessStateChanged (state);
+}
+
+uint32_t NativeProcessProtocol::GetStopID () const
+{
+ Mutex::Locker locker (m_state_mutex);
+ return m_stop_id;
+}
+
+void
+NativeProcessProtocol::DoStopIDBumped (uint32_t /* newBumpId */)
+{
+ // Default implementation does nothing.
+}
diff --git a/source/Host/common/NativeProcessProtocol.h b/source/Host/common/NativeProcessProtocol.h
new file mode 100644
index 000000000000..035a264e172e
--- /dev/null
+++ b/source/Host/common/NativeProcessProtocol.h
@@ -0,0 +1,333 @@
+//===-- NativeProcessProtocol.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_NativeProcessProtocol_h_
+#define liblldb_NativeProcessProtocol_h_
+
+#include <vector>
+
+#include "lldb/lldb-private-forward.h"
+#include "lldb/lldb-types.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Host/Mutex.h"
+
+#include "NativeBreakpointList.h"
+
+namespace lldb_private
+{
+ class MemoryRegionInfo;
+ class ResumeActionList;
+
+ //------------------------------------------------------------------
+ // NativeProcessProtocol
+ //------------------------------------------------------------------
+ class NativeProcessProtocol :
+ public std::enable_shared_from_this<NativeProcessProtocol>
+ {
+ friend class SoftwareBreakpoint;
+
+ public:
+ static NativeProcessProtocol *
+ CreateInstance (lldb::pid_t pid);
+
+ // lldb_private::Host calls should be used to launch a process for debugging, and
+ // then the process should be attached to. When attaching to a process
+ // lldb_private::Host calls should be used to locate the process to attach to,
+ // and then this function should be called.
+ NativeProcessProtocol (lldb::pid_t pid);
+
+ public:
+ virtual ~NativeProcessProtocol ()
+ {
+ }
+
+ virtual Error
+ Resume (const ResumeActionList &resume_actions) = 0;
+
+ virtual Error
+ Halt () = 0;
+
+ virtual Error
+ Detach () = 0;
+
+ //------------------------------------------------------------------
+ /// 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;
+
+ virtual Error
+ Kill () = 0;
+
+ //----------------------------------------------------------------------
+ // Memory and memory region functions
+ //----------------------------------------------------------------------
+
+ virtual Error
+ GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info);
+
+ virtual Error
+ ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) = 0;
+
+ virtual Error
+ WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) = 0;
+
+ virtual Error
+ AllocateMemory (lldb::addr_t size, uint32_t permissions, lldb::addr_t &addr) = 0;
+
+ virtual Error
+ DeallocateMemory (lldb::addr_t addr) = 0;
+
+ virtual lldb::addr_t
+ GetSharedLibraryInfoAddress () = 0;
+
+ virtual bool
+ IsAlive () const;
+
+ virtual size_t
+ UpdateThreads () = 0;
+
+ virtual bool
+ GetArchitecture (ArchSpec &arch) const = 0;
+
+ //----------------------------------------------------------------------
+ // Breakpoint functions
+ //----------------------------------------------------------------------
+ virtual Error
+ SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) = 0;
+
+ virtual Error
+ RemoveBreakpoint (lldb::addr_t addr);
+
+ virtual Error
+ EnableBreakpoint (lldb::addr_t addr);
+
+ virtual Error
+ DisableBreakpoint (lldb::addr_t addr);
+
+ //----------------------------------------------------------------------
+ // Watchpoint functions
+ //----------------------------------------------------------------------
+ virtual uint32_t
+ GetMaxWatchpoints () const;
+
+ virtual Error
+ SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware);
+
+ virtual Error
+ RemoveWatchpoint (lldb::addr_t addr);
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+ lldb::pid_t
+ GetID() const
+ {
+ return m_pid;
+ }
+
+ lldb::StateType
+ GetState () const;
+
+ bool
+ IsRunning () const
+ {
+ return m_state == lldb::eStateRunning || IsStepping();
+ }
+
+ bool
+ IsStepping () const
+ {
+ return m_state == lldb::eStateStepping;
+ }
+
+ bool
+ CanResume () const
+ {
+ return m_state == lldb::eStateStopped;
+ }
+
+ bool
+ GetByteOrder (lldb::ByteOrder &byte_order) const;
+
+ //----------------------------------------------------------------------
+ // Exit Status
+ //----------------------------------------------------------------------
+ virtual bool
+ GetExitStatus (lldb_private::ExitType *exit_type, int *status, std::string &exit_description);
+
+ virtual bool
+ SetExitStatus (lldb_private::ExitType exit_type, int status, const char *exit_description, bool bNotifyStateChange);
+
+ //----------------------------------------------------------------------
+ // Access to threads
+ //----------------------------------------------------------------------
+ NativeThreadProtocolSP
+ GetThreadAtIndex (uint32_t idx);
+
+ NativeThreadProtocolSP
+ GetThreadByID (lldb::tid_t tid);
+
+ void
+ SetCurrentThreadID (lldb::tid_t tid)
+ {
+ m_current_thread_id = tid;
+ }
+
+ lldb::tid_t
+ GetCurrentThreadID ()
+ {
+ return m_current_thread_id;
+ }
+
+ NativeThreadProtocolSP
+ GetCurrentThread ()
+ {
+ return GetThreadByID (m_current_thread_id);
+ }
+
+ //----------------------------------------------------------------------
+ // Access to inferior stdio
+ //----------------------------------------------------------------------
+ virtual
+ int GetTerminalFileDescriptor ()
+ {
+ return m_terminal_fd;
+ }
+
+ //----------------------------------------------------------------------
+ // Stop id interface
+ //----------------------------------------------------------------------
+
+ uint32_t
+ GetStopID () const;
+
+ // ---------------------------------------------------------------------
+ // Callbacks for low-level process state changes
+ // ---------------------------------------------------------------------
+ class NativeDelegate
+ {
+ public:
+ virtual
+ ~NativeDelegate () {}
+
+ virtual void
+ InitializeDelegate (NativeProcessProtocol *process) = 0;
+
+ virtual void
+ ProcessStateChanged (NativeProcessProtocol *process, lldb::StateType state) = 0;
+
+ virtual void
+ DidExec (NativeProcessProtocol *process) = 0;
+ };
+
+ //------------------------------------------------------------------
+ /// Register a native delegate.
+ ///
+ /// Clients can register nofication callbacks by passing in a
+ /// NativeDelegate impl and passing it into this function.
+ ///
+ /// Note: it is required that the lifetime of the
+ /// native_delegate outlive the NativeProcessProtocol.
+ ///
+ /// @param[in] native_delegate
+ /// A NativeDelegate impl to be called when certain events
+ /// happen within the NativeProcessProtocol or related threads.
+ ///
+ /// @return
+ /// true if the delegate was registered successfully;
+ /// false if the delegate was already registered.
+ ///
+ /// @see NativeProcessProtocol::NativeDelegate.
+ //------------------------------------------------------------------
+ bool
+ RegisterNativeDelegate (NativeDelegate &native_delegate);
+
+ //------------------------------------------------------------------
+ /// Unregister a native delegate previously registered.
+ ///
+ /// @param[in] native_delegate
+ /// A NativeDelegate impl previously registered with this process.
+ ///
+ /// @return Returns \b true if the NativeDelegate was
+ /// successfully removed from the process, \b false otherwise.
+ ///
+ /// @see NativeProcessProtocol::NativeDelegate
+ //------------------------------------------------------------------
+ bool
+ UnregisterNativeDelegate (NativeDelegate &native_delegate);
+
+ protected:
+ lldb::pid_t m_pid;
+
+ std::vector<NativeThreadProtocolSP> m_threads;
+ lldb::tid_t m_current_thread_id;
+ mutable Mutex m_threads_mutex;
+
+ lldb::StateType m_state;
+ mutable Mutex m_state_mutex;
+
+ lldb_private::ExitType m_exit_type;
+ int m_exit_status;
+ std::string m_exit_description;
+ Mutex m_delegates_mutex;
+ std::vector<NativeDelegate*> m_delegates;
+ NativeBreakpointList m_breakpoint_list;
+ int m_terminal_fd;
+ uint32_t m_stop_id;
+
+ // -----------------------------------------------------------
+ // Internal interface for state handling
+ // -----------------------------------------------------------
+ void
+ SetState (lldb::StateType state, bool notify_delegates = true);
+
+ // Derived classes need not impelment this. It can be used as a
+ // hook to clear internal caches that should be invalidated when
+ // stop ids change.
+ //
+ // Note this function is called with the state mutex obtained
+ // by the caller.
+ virtual void
+ DoStopIDBumped (uint32_t newBumpId);
+
+ // -----------------------------------------------------------
+ // Internal interface for software breakpoints
+ // -----------------------------------------------------------
+ Error
+ SetSoftwareBreakpoint (lldb::addr_t addr, uint32_t size_hint);
+
+ virtual Error
+ GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) = 0;
+
+ // -----------------------------------------------------------
+ /// Notify the delegate that an exec occurred.
+ ///
+ /// Provide a mechanism for a delegate to clear out any exec-
+ /// sensitive data.
+ // -----------------------------------------------------------
+ void
+ NotifyDidExec ();
+
+ private:
+
+ void
+ SynchronouslyNotifyProcessStateChanged (lldb::StateType state);
+ };
+}
+
+#endif // #ifndef liblldb_NativeProcessProtocol_h_
diff --git a/source/Host/common/NativeThreadProtocol.cpp b/source/Host/common/NativeThreadProtocol.cpp
new file mode 100644
index 000000000000..6cef5b1fa2d2
--- /dev/null
+++ b/source/Host/common/NativeThreadProtocol.cpp
@@ -0,0 +1,97 @@
+//===-- NativeThreadProtocol.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NativeThreadProtocol.h"
+
+#include "NativeProcessProtocol.h"
+#include "lldb/Target/NativeRegisterContext.h"
+#include "SoftwareBreakpoint.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+NativeThreadProtocol::NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid) :
+ m_process_wp (process->shared_from_this ()),
+ m_tid (tid)
+{
+}
+
+Error
+NativeThreadProtocol::ReadRegister (uint32_t reg, RegisterValue &reg_value)
+{
+ NativeRegisterContextSP register_context_sp = GetRegisterContext ();
+ if (!register_context_sp)
+ return Error ("no register context");
+
+ const RegisterInfo *const reg_info = register_context_sp->GetRegisterInfoAtIndex (reg);
+ if (!reg_info)
+ return Error ("no register info for reg num %" PRIu32, reg);
+
+ return register_context_sp->ReadRegister (reg_info, reg_value);;
+}
+
+Error
+NativeThreadProtocol::WriteRegister (uint32_t reg, const RegisterValue &reg_value)
+{
+ NativeRegisterContextSP register_context_sp = GetRegisterContext ();
+ if (!register_context_sp)
+ return Error ("no register context");
+
+ const RegisterInfo *const reg_info = register_context_sp->GetRegisterInfoAtIndex (reg);
+ if (!reg_info)
+ return Error ("no register info for reg num %" PRIu32, reg);
+
+ return register_context_sp->WriteRegister (reg_info, reg_value);
+}
+
+Error
+NativeThreadProtocol::SaveAllRegisters (lldb::DataBufferSP &data_sp)
+{
+ NativeRegisterContextSP register_context_sp = GetRegisterContext ();
+ if (!register_context_sp)
+ return Error ("no register context");
+ return register_context_sp->WriteAllRegisterValues (data_sp);
+}
+
+Error
+NativeThreadProtocol::RestoreAllRegisters (lldb::DataBufferSP &data_sp)
+{
+ NativeRegisterContextSP register_context_sp = GetRegisterContext ();
+ if (!register_context_sp)
+ return Error ("no register context");
+ return register_context_sp->ReadAllRegisterValues (data_sp);
+}
+
+NativeProcessProtocolSP
+NativeThreadProtocol::GetProcess ()
+{
+ return m_process_wp.lock ();
+}
+
+uint32_t
+NativeThreadProtocol::TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const
+{
+ // Default: no translation. Do the real translation where there
+ // is access to the host signal numbers.
+ switch (stop_info.reason)
+ {
+ case eStopReasonSignal:
+ return stop_info.details.signal.signo;
+ break;
+
+ case eStopReasonException:
+ // FIXME verify the way to specify pass-thru here.
+ return static_cast<uint32_t> (stop_info.details.exception.type);
+ break;
+
+ default:
+ assert (0 && "unexpected stop_info.reason found");
+ return 0;
+ }
+}
diff --git a/source/Host/common/NativeThreadProtocol.h b/source/Host/common/NativeThreadProtocol.h
new file mode 100644
index 000000000000..9b404be500b9
--- /dev/null
+++ b/source/Host/common/NativeThreadProtocol.h
@@ -0,0 +1,85 @@
+//===-- NativeThreadProtocol.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_NativeThreadProtocol_h_
+#define liblldb_NativeThreadProtocol_h_
+
+#include <memory>
+
+#include "lldb/lldb-private-forward.h"
+#include "lldb/lldb-types.h"
+#include "lldb/Host/Debug.h"
+
+namespace lldb_private
+{
+ //------------------------------------------------------------------
+ // NativeThreadProtocol
+ //------------------------------------------------------------------
+ class NativeThreadProtocol:
+ public std::enable_shared_from_this<NativeThreadProtocol>
+ {
+ public:
+ NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid);
+
+ virtual ~NativeThreadProtocol()
+ {
+ }
+
+ virtual const char *
+ GetName() = 0;
+
+ virtual lldb::StateType
+ GetState () = 0;
+
+ virtual NativeRegisterContextSP
+ GetRegisterContext () = 0;
+
+ virtual Error
+ ReadRegister (uint32_t reg, RegisterValue &reg_value);
+
+ virtual Error
+ WriteRegister (uint32_t reg, const RegisterValue &reg_value);
+
+ virtual Error
+ SaveAllRegisters (lldb::DataBufferSP &data_sp);
+
+ virtual Error
+ RestoreAllRegisters (lldb::DataBufferSP &data_sp);
+
+ virtual bool
+ GetStopReason (ThreadStopInfo &stop_info) = 0;
+
+ virtual uint32_t
+ TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const;
+
+ lldb::tid_t
+ GetID() const
+ {
+ return m_tid;
+ }
+
+ NativeProcessProtocolSP
+ GetProcess ();
+
+ // ---------------------------------------------------------------------
+ // Thread-specific watchpoints
+ // ---------------------------------------------------------------------
+ virtual Error
+ SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) = 0;
+
+ virtual Error
+ RemoveWatchpoint (lldb::addr_t addr) = 0;
+
+ protected:
+ NativeProcessProtocolWP m_process_wp;
+ lldb::tid_t m_tid;
+ };
+}
+
+#endif // #ifndef liblldb_NativeThreadProtocol_h_
diff --git a/source/Host/common/OptionParser.cpp b/source/Host/common/OptionParser.cpp
index cf133597cb84..a91e764bfe3b 100644
--- a/source/Host/common/OptionParser.cpp
+++ b/source/Host/common/OptionParser.cpp
@@ -8,11 +8,10 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/OptionParser.h"
-
-#if (!defined( _MSC_VER ) && defined( _WIN32 ))
-#define _BSD_SOURCE // Required so that getopt.h defines optreset
-#endif
#include "lldb/Host/HostGetOpt.h"
+#include "lldb/lldb-private-types.h"
+
+#include <vector>
using namespace lldb_private;
@@ -40,7 +39,19 @@ OptionParser::Parse (int argc,
const Option *longopts,
int *longindex)
{
- return getopt_long_only(argc, argv, optstring, (const option*)longopts, longindex);
+ std::vector<option> opts;
+ while (longopts->definition != nullptr)
+ {
+ option opt;
+ opt.flag = longopts->flag;
+ opt.val = longopts->val;
+ opt.name = longopts->definition->long_option;
+ opt.has_arg = longopts->definition->option_has_arg;
+ opts.push_back(opt);
+ ++longopts;
+ }
+ opts.push_back(option());
+ return getopt_long_only(argc, argv, optstring, &opts[0], longindex);
}
char*
diff --git a/source/Host/common/Pipe.cpp b/source/Host/common/Pipe.cpp
new file mode 100644
index 000000000000..4db0e32c93b7
--- /dev/null
+++ b/source/Host/common/Pipe.cpp
@@ -0,0 +1,171 @@
+//===-- 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 <io.h>
+#include <fcntl.h>
+#else
+#include <unistd.h>
+#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/Socket.cpp b/source/Host/common/Socket.cpp
new file mode 100644
index 000000000000..31e3228497ec
--- /dev/null
+++ b/source/Host/common/Socket.cpp
@@ -0,0 +1,662 @@
+//===-- Socket.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/Socket.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Host/Config.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/SocketAddress.h"
+#include "lldb/Host/TimeValue.h"
+#include "lldb/Interpreter/Args.h"
+
+#ifndef LLDB_DISABLE_POSIX
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#endif
+
+using namespace lldb;
+using namespace lldb_private;
+
+#if defined(_WIN32)
+typedef const char * set_socket_option_arg_type;
+typedef char * get_socket_option_arg_type;
+const NativeSocket Socket::kInvalidSocketValue = INVALID_SOCKET;
+#else // #if defined(_WIN32)
+typedef const void * set_socket_option_arg_type;
+typedef void * get_socket_option_arg_type;
+const NativeSocket Socket::kInvalidSocketValue = -1;
+#endif // #if defined(_WIN32)
+
+Socket::Socket(NativeSocket socket, SocketProtocol protocol, bool should_close)
+ : IOObject(eFDTypeSocket, should_close)
+ , m_protocol(protocol)
+ , m_socket(socket)
+{
+
+}
+
+Socket::~Socket()
+{
+ Close();
+}
+
+Error Socket::TcpConnect(llvm::StringRef host_and_port, Socket *&socket)
+{
+ // Store the result in a unique_ptr in case we error out, the memory will get correctly freed.
+ std::unique_ptr<Socket> final_socket;
+ NativeSocket sock = kInvalidSocketValue;
+ Error error;
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST));
+ if (log)
+ log->Printf ("Socket::TcpConnect (host/port = %s)", host_and_port.data());
+
+ std::string host_str;
+ std::string port_str;
+ int32_t port = INT32_MIN;
+ if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error))
+ return error;
+
+ // Create the socket
+ sock = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sock == kInvalidSocketValue)
+ {
+ // TODO: On Windows, use WSAGetLastError().
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ // Since they both refer to the same socket descriptor, arbitrarily choose the send socket to
+ // be the owner.
+ final_socket.reset(new Socket(sock, ProtocolTcp, true));
+
+ // Enable local address reuse
+ final_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
+
+ struct sockaddr_in sa;
+ ::memset (&sa, 0, sizeof (sa));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons (port);
+
+ int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
+
+ if (inet_pton_result <= 0)
+ {
+ struct hostent *host_entry = gethostbyname (host_str.c_str());
+ if (host_entry)
+ host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
+ inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
+ if (inet_pton_result <= 0)
+ {
+ // TODO: On Windows, use WSAGetLastError()
+ if (inet_pton_result == -1)
+ error.SetErrorToErrno();
+ else
+ error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
+
+ return error;
+ }
+ }
+
+ if (-1 == ::connect (sock, (const struct sockaddr *)&sa, sizeof(sa)))
+ {
+ // TODO: On Windows, use WSAGetLastError()
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ // Keep our TCP packets coming without any delays.
+ final_socket->SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
+ error.Clear();
+ socket = final_socket.release();
+ return error;
+}
+
+Error Socket::TcpListen(llvm::StringRef host_and_port, Socket *&socket, Predicate<uint16_t>* predicate)
+{
+ std::unique_ptr<Socket> listen_socket;
+ NativeSocket listen_sock = kInvalidSocketValue;
+ Error error;
+
+ const sa_family_t family = AF_INET;
+ const int socktype = SOCK_STREAM;
+ const int protocol = IPPROTO_TCP;
+ listen_sock = ::socket (family, socktype, protocol);
+ if (listen_sock == kInvalidSocketValue)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ listen_socket.reset(new Socket(listen_sock, ProtocolTcp, true));
+
+ // enable local address reuse
+ listen_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("ConnectionFileDescriptor::SocketListen (%s)", host_and_port.data());
+
+ std::string host_str;
+ std::string port_str;
+ int32_t port = INT32_MIN;
+ if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error))
+ return error;
+
+ SocketAddress anyaddr;
+ if (anyaddr.SetToAnyAddress (family, port))
+ {
+ int err = ::bind (listen_sock, anyaddr, anyaddr.GetLength());
+ if (err == -1)
+ {
+ // TODO: On Windows, use WSAGetLastError()
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ err = ::listen (listen_sock, 1);
+ if (err == -1)
+ {
+ // TODO: On Windows, use WSAGetLastError()
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ // We were asked to listen on port zero which means we
+ // must now read the actual port that was given to us
+ // as port zero is a special code for "find an open port
+ // for me".
+ if (port == 0)
+ port = listen_socket->GetPortNumber();
+
+ // Set the port predicate since when doing a listen://<host>:<port>
+ // it often needs to accept the incoming connection which is a blocking
+ // system call. Allowing access to the bound port using a predicate allows
+ // us to wait for the port predicate to be set to a non-zero value from
+ // another thread in an efficient manor.
+ if (predicate)
+ predicate->SetValue(port, eBroadcastAlways);
+
+ socket = listen_socket.release();
+ }
+
+ return error;
+}
+
+Error Socket::BlockingAccept(llvm::StringRef host_and_port, Socket *&socket)
+{
+ Error error;
+ std::string host_str;
+ std::string port_str;
+ int32_t port;
+ if (!DecodeHostAndPort(host_and_port, host_str, port_str, port, &error))
+ return error;
+
+ const sa_family_t family = AF_INET;
+ const int socktype = SOCK_STREAM;
+ const int protocol = IPPROTO_TCP;
+ SocketAddress listen_addr;
+ if (host_str.empty())
+ listen_addr.SetToLocalhost(family, port);
+ else if (host_str.compare("*") == 0)
+ listen_addr.SetToAnyAddress(family, port);
+ else
+ {
+ if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol))
+ {
+ error.SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str());
+ return error;
+ }
+ }
+
+ bool accept_connection = false;
+ std::unique_ptr<Socket> accepted_socket;
+
+ // Loop until we are happy with our connection
+ while (!accept_connection)
+ {
+ struct sockaddr_in accept_addr;
+ ::memset (&accept_addr, 0, sizeof accept_addr);
+#if !(defined (__linux__) || defined(_WIN32))
+ accept_addr.sin_len = sizeof accept_addr;
+#endif
+ socklen_t accept_addr_len = sizeof accept_addr;
+
+ int sock = ::accept (this->GetNativeSocket(), (struct sockaddr *)&accept_addr, &accept_addr_len);
+
+ if (sock == kInvalidSocketValue)
+ {
+ // TODO: On Windows, use WSAGetLastError()
+ error.SetErrorToErrno();
+ break;
+ }
+
+ bool is_same_addr = true;
+#if !(defined(__linux__) || (defined(_WIN32)))
+ is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len);
+#endif
+ if (is_same_addr)
+ is_same_addr = (accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr);
+
+ if (is_same_addr || (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY))
+ {
+ accept_connection = true;
+ // Since both sockets have the same descriptor, arbitrarily choose the send
+ // socket to be the owner.
+ accepted_socket.reset(new Socket(sock, ProtocolTcp, true));
+ }
+ else
+ {
+ const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
+ const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
+ ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n",
+ accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
+ listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
+ accepted_socket.reset();
+ }
+ }
+
+ if (!accepted_socket)
+ return error;
+
+ // Keep our TCP packets coming without any delays.
+ accepted_socket->SetOption (IPPROTO_TCP, TCP_NODELAY, 1);
+ error.Clear();
+ socket = accepted_socket.release();
+ return error;
+
+}
+
+Error Socket::UdpConnect(llvm::StringRef host_and_port, Socket *&send_socket, Socket *&recv_socket)
+{
+ std::unique_ptr<Socket> final_send_socket;
+ std::unique_ptr<Socket> final_recv_socket;
+ NativeSocket final_send_fd = kInvalidSocketValue;
+ NativeSocket final_recv_fd = kInvalidSocketValue;
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("Socket::UdpConnect (host/port = %s)", host_and_port.data());
+
+ Error error;
+ std::string host_str;
+ std::string port_str;
+ int32_t port = INT32_MIN;
+ if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error))
+ return error;
+
+ // 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);
+ if (final_recv_fd == kInvalidSocketValue)
+ {
+ // Socket creation failed...
+ // TODO: On Windows, use WSAGetLastError().
+ error.SetErrorToErrno();
+ }
+ else
+ {
+ final_recv_socket.reset(new Socket(final_recv_fd, ProtocolUdp, true));
+
+ // Socket was created, now lets bind to the requested port
+ SocketAddress addr;
+ addr.SetToAnyAddress (AF_INET, 0);
+
+ if (::bind (final_recv_fd, addr, addr.GetLength()) == -1)
+ {
+ // Bind failed...
+ // TODO: On Windows use WSAGetLastError()
+ error.SetErrorToErrno();
+ }
+ }
+
+ assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid()));
+ if (error.Fail())
+ return error;
+
+ // At this point we have setup the receive port, now we need to
+ // setup the UDP send socket
+
+ struct addrinfo hints;
+ struct addrinfo *service_info_list = NULL;
+
+ ::memset (&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list);
+ if (err != 0)
+ {
+ error.SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)",
+ host_str.c_str(),
+ port_str.c_str(),
+ err,
+ gai_strerror(err));
+ return error;
+ }
+
+ for (struct addrinfo *service_info_ptr = service_info_list;
+ 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);
+
+ if (final_send_fd != kInvalidSocketValue)
+ {
+ final_send_socket.reset(new Socket(final_send_fd, ProtocolUdp, true));
+ final_send_socket->m_udp_send_sockaddr = service_info_ptr;
+ break;
+ }
+ else
+ continue;
+ }
+
+ :: freeaddrinfo (service_info_list);
+
+ if (final_send_fd == kInvalidSocketValue)
+ {
+ // TODO: On Windows, use WSAGetLastError().
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ send_socket = final_send_socket.release();
+ recv_socket = final_recv_socket.release();
+ error.Clear();
+ return error;
+}
+
+Error Socket::UnixDomainConnect(llvm::StringRef name, Socket *&socket)
+{
+ Error error;
+#ifndef LLDB_DISABLE_POSIX
+ std::unique_ptr<Socket> final_socket;
+
+ // Open the socket that was passed in as an option
+ struct sockaddr_un saddr_un;
+ int fd = ::socket (AF_UNIX, SOCK_STREAM, 0);
+ if (fd == kInvalidSocketValue)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ final_socket.reset(new Socket(fd, ProtocolUnixDomain, true));
+
+ saddr_un.sun_family = AF_UNIX;
+ ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1);
+ saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
+ saddr_un.sun_len = SUN_LEN (&saddr_un);
+#endif
+
+ if (::connect (fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ socket = final_socket.release();
+#else
+ error.SetErrorString("Unix domain sockets are not supported on this platform.");
+#endif
+ return error;
+}
+
+Error Socket::UnixDomainAccept(llvm::StringRef name, Socket *&socket)
+{
+ Error error;
+#ifndef LLDB_DISABLE_POSIX
+ struct sockaddr_un saddr_un;
+ std::unique_ptr<Socket> listen_socket;
+ std::unique_ptr<Socket> final_socket;
+ NativeSocket listen_fd = kInvalidSocketValue;
+ NativeSocket socket_fd = kInvalidSocketValue;
+
+ listen_fd = ::socket (AF_UNIX, SOCK_STREAM, 0);
+ if (listen_fd == kInvalidSocketValue)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ listen_socket.reset(new Socket(listen_fd, ProtocolUnixDomain, true));
+
+ saddr_un.sun_family = AF_UNIX;
+ ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1);
+ saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
+ saddr_un.sun_len = SUN_LEN (&saddr_un);
+#endif
+
+ FileSystem::Unlink(name.data());
+ bool success = false;
+ if (::bind (listen_fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0)
+ {
+ if (::listen (listen_fd, 5) == 0)
+ {
+ socket_fd = ::accept (listen_fd, NULL, 0);
+ if (socket_fd > 0)
+ {
+ final_socket.reset(new Socket(socket_fd, ProtocolUnixDomain, true));
+ success = true;
+ }
+ }
+ }
+
+ if (!success)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+ // We are done with the listen port
+ listen_socket.reset();
+
+ socket = final_socket.release();
+#else
+ error.SetErrorString("Unix domain sockets are not supported on this platform.");
+#endif
+ return error;
+}
+
+bool
+Socket::DecodeHostAndPort(llvm::StringRef host_and_port,
+ std::string &host_str,
+ std::string &port_str,
+ int32_t& port,
+ Error *error_ptr)
+{
+ static RegularExpression g_regex ("([^:]+):([0-9]+)");
+ RegularExpression::Match regex_match(2);
+ if (g_regex.Execute (host_and_port.data(), &regex_match))
+ {
+ if (regex_match.GetMatchAtIndex (host_and_port.data(), 1, host_str) &&
+ regex_match.GetMatchAtIndex (host_and_port.data(), 2, port_str))
+ {
+ port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN);
+ if (port != INT32_MIN)
+ {
+ if (error_ptr)
+ error_ptr->Clear();
+ return true;
+ }
+ }
+ }
+
+ // If this was unsuccessful, then check if it's simply a signed 32-bit integer, representing
+ // a port with an empty host.
+ host_str.clear();
+ port_str.clear();
+ port = Args::StringToSInt32(host_and_port.data(), INT32_MIN);
+ if (port != INT32_MIN)
+ {
+ port_str = host_and_port;
+ return true;
+ }
+
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data());
+ return false;
+}
+
+IOObject::WaitableHandle Socket::GetWaitableHandle()
+{
+ // TODO: On Windows, use WSAEventSelect
+ return m_socket;
+}
+
+Error Socket::Read (void *buf, size_t &num_bytes)
+{
+ Error error;
+ int bytes_received = 0;
+ do
+ {
+ bytes_received = ::recv (m_socket, static_cast<char *>(buf), num_bytes, 0);
+ // TODO: Use WSAGetLastError on windows.
+ } while (bytes_received < 0 && errno == EINTR);
+
+ if (bytes_received < 0)
+ {
+ error.SetErrorToErrno();
+ num_bytes = 0;
+ }
+ else
+ num_bytes = bytes_received;
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_COMMUNICATION));
+ if (log)
+ {
+ log->Printf ("%p Socket::Read() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
+ static_cast<void*>(this),
+ static_cast<uint64_t>(m_socket),
+ buf,
+ static_cast<uint64_t>(num_bytes),
+ static_cast<int64_t>(bytes_received),
+ error.AsCString());
+ }
+
+ return error;
+}
+
+Error Socket::Write (const void *buf, size_t &num_bytes)
+{
+ Error error;
+ int bytes_sent = 0;
+ do
+ {
+ if (m_protocol == ProtocolUdp)
+ {
+ bytes_sent = ::sendto (m_socket,
+ static_cast<const char*>(buf),
+ num_bytes,
+ 0,
+ m_udp_send_sockaddr,
+ m_udp_send_sockaddr.GetLength());
+ }
+ else
+ bytes_sent = ::send (m_socket, static_cast<const char *>(buf), num_bytes, 0);
+ // TODO: Use WSAGetLastError on windows.
+ } while (bytes_sent < 0 && errno == EINTR);
+
+ if (bytes_sent < 0)
+ {
+ // TODO: On Windows, use WSAGEtLastError.
+ error.SetErrorToErrno();
+ num_bytes = 0;
+ }
+ else
+ num_bytes = bytes_sent;
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST));
+ if (log)
+ {
+ log->Printf ("%p Socket::Write() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
+ static_cast<void*>(this),
+ static_cast<uint64_t>(m_socket),
+ buf,
+ static_cast<uint64_t>(num_bytes),
+ static_cast<int64_t>(bytes_sent),
+ error.AsCString());
+ }
+
+ return error;
+}
+
+Error Socket::PreDisconnect()
+{
+ Error error;
+ return error;
+}
+
+Error Socket::Close()
+{
+ Error error;
+ if (!IsValid() || !m_should_close_fd)
+ return error;
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("%p Socket::Close (fd = %i)", static_cast<void*>(this), m_socket);
+
+#if defined(_WIN32)
+ bool success = !!closesocket(m_socket);
+#else
+ bool success = !!::close (m_socket);
+#endif
+ // A reference to a FD was passed in, set it to an invalid value
+ m_socket = kInvalidSocketValue;
+ if (!success)
+ {
+ // TODO: On Windows, use WSAGetLastError().
+ error.SetErrorToErrno();
+ }
+
+ return error;
+}
+
+
+int Socket::GetOption(int level, int option_name, int &option_value)
+{
+ get_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value);
+ socklen_t option_value_size = sizeof(int);
+ return ::getsockopt(m_socket, level, option_name, option_value_p, &option_value_size);
+}
+
+int Socket::SetOption(int level, int option_name, int option_value)
+{
+ set_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value);
+ return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value));
+}
+
+uint16_t Socket::GetPortNumber(const NativeSocket& socket)
+{
+ // We bound to port zero, so we need to figure out which port we actually bound to
+ if (socket >= 0)
+ {
+ SocketAddress sock_addr;
+ socklen_t sock_addr_len = sock_addr.GetMaxLength ();
+ if (::getsockname (socket, sock_addr, &sock_addr_len) == 0)
+ return sock_addr.GetPort ();
+ }
+ return 0;
+}
+
+// Return the port number that is being used by the socket.
+uint16_t Socket::GetPortNumber() const
+{
+ return GetPortNumber(m_socket);
+}
diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp
index 75f3cd13f586..a952a83185fb 100644
--- a/source/Host/common/SocketAddress.cpp
+++ b/source/Host/common/SocketAddress.cpp
@@ -11,7 +11,7 @@
#include <stddef.h>
// C Includes
-#if !defined(_MSC_VER)
+#if !defined(_WIN32)
#include <arpa/inet.h>
#endif
#include <assert.h>
@@ -90,6 +90,7 @@ GetFamilyLength (sa_family_t family)
case AF_INET6: return sizeof(struct sockaddr_in6);
}
assert(0 && "Unsupported address family");
+ return 0;
}
socklen_t
diff --git a/source/Host/common/SoftwareBreakpoint.cpp b/source/Host/common/SoftwareBreakpoint.cpp
new file mode 100644
index 000000000000..fe2f504ebc71
--- /dev/null
+++ b/source/Host/common/SoftwareBreakpoint.cpp
@@ -0,0 +1,296 @@
+//===-- SoftwareBreakpoint.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SoftwareBreakpoint.h"
+
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Host/Debug.h"
+#include "lldb/Host/Mutex.h"
+
+#include "NativeProcessProtocol.h"
+
+using namespace lldb_private;
+
+// -------------------------------------------------------------------
+// static members
+// -------------------------------------------------------------------
+
+Error
+SoftwareBreakpoint::CreateSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint, NativeBreakpointSP &breakpoint_sp)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
+
+ // Validate the address.
+ if (addr == LLDB_INVALID_ADDRESS)
+ return Error ("SoftwareBreakpoint::%s invalid load address specified.", __FUNCTION__);
+
+ // Ask the NativeProcessProtocol subclass to fill in the correct software breakpoint
+ // trap for the breakpoint site.
+ size_t bp_opcode_size = 0;
+ const uint8_t *bp_opcode_bytes = NULL;
+ Error error = process.GetSoftwareBreakpointTrapOpcode (size_hint, bp_opcode_size, bp_opcode_bytes);
+
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s failed to retrieve software breakpoint trap opcode: %s", __FUNCTION__, error.AsCString ());
+ return error;
+ }
+
+ // Validate size of trap opcode.
+ if (bp_opcode_size == 0)
+ {
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s failed to retrieve any trap opcodes", __FUNCTION__);
+ return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned zero, unable to get breakpoint trap for address 0x%" PRIx64, addr);
+ }
+
+ if (bp_opcode_size > MAX_TRAP_OPCODE_SIZE)
+ {
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s cannot support %lu trapcode bytes, max size is %lu", __FUNCTION__, bp_opcode_size, MAX_TRAP_OPCODE_SIZE);
+ return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned too many trap opcode bytes: requires %lu but we only support a max of %lu", bp_opcode_size, MAX_TRAP_OPCODE_SIZE);
+ }
+
+ // Validate that we received opcodes.
+ if (!bp_opcode_bytes)
+ {
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s failed to retrieve trap opcode bytes", __FUNCTION__);
+ return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned NULL trap opcode bytes, unable to get breakpoint trap for address 0x%" PRIx64, addr);
+ }
+
+ // Enable the breakpoint.
+ uint8_t saved_opcode_bytes [MAX_TRAP_OPCODE_SIZE];
+ error = EnableSoftwareBreakpoint (process, addr, bp_opcode_size, bp_opcode_bytes, saved_opcode_bytes);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s: failed to enable new breakpoint at 0x%" PRIx64 ": %s", __FUNCTION__, addr, error.AsCString ());
+ return error;
+ }
+
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, addr);
+
+ // Set the breakpoint and verified it was written properly. Now
+ // create a breakpoint remover that understands how to undo this
+ // breakpoint.
+ breakpoint_sp.reset (new SoftwareBreakpoint (process, addr, saved_opcode_bytes, bp_opcode_bytes, bp_opcode_size));
+ return Error ();
+}
+
+Error
+SoftwareBreakpoint::EnableSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t bp_opcode_size, const uint8_t *bp_opcode_bytes, uint8_t *saved_opcode_bytes)
+{
+ assert (bp_opcode_size <= MAX_TRAP_OPCODE_SIZE && "bp_opcode_size out of valid range");
+ assert (bp_opcode_bytes && "bp_opcode_bytes is NULL");
+ assert (saved_opcode_bytes && "saved_opcode_bytes is NULL");
+
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
+
+ // Save the original opcodes by reading them so we can restore later.
+ lldb::addr_t bytes_read = 0;
+
+ Error error = process.ReadMemory(addr, saved_opcode_bytes, static_cast<lldb::addr_t> (bp_opcode_size), bytes_read);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to set breakpoint: %s", __FUNCTION__, error.AsCString ());
+ return error;
+ }
+
+ // Ensure we read as many bytes as we expected.
+ if (bytes_read != static_cast<lldb::addr_t> (bp_opcode_size))
+ {
+ if (log)
+ log->Printf ("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);
+ 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);
+ }
+
+ // 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<lldb::addr_t> (bp_opcode_size), bytes_written);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s failed to write memory while attempting to set breakpoint: %s", __FUNCTION__, error.AsCString ());
+ return error;
+ }
+
+ // Ensure we wrote as many bytes as we expected.
+ if (bytes_written != static_cast<lldb::addr_t> (bp_opcode_size))
+ {
+ error.SetErrorStringWithFormat("SoftwareBreakpoint::%s failed write memory while attempting to set breakpoint: attempted to write %lu bytes but only wrote %" PRIu64, __FUNCTION__, bp_opcode_size, bytes_written);
+ if (log)
+ log->PutCString (error.AsCString ());
+ return error;
+ }
+
+ uint8_t verify_bp_opcode_bytes [MAX_TRAP_OPCODE_SIZE];
+ lldb::addr_t verify_bytes_read = 0;
+ error = process.ReadMemory(addr, verify_bp_opcode_bytes, static_cast<lldb::addr_t> (bp_opcode_size), verify_bytes_read);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to verify the breakpoint set: %s", __FUNCTION__, error.AsCString ());
+ return error;
+ }
+
+ // Ensure we read as many verification bytes as we expected.
+ if (verify_bytes_read != static_cast<lldb::addr_t> (bp_opcode_size))
+ {
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to verify breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, verify_bytes_read);
+ return Error ("SoftwareBreakpoint::%s failed to read memory while attempting to verify breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, verify_bytes_read);
+ }
+
+ if (::memcmp(bp_opcode_bytes, verify_bp_opcode_bytes, bp_opcode_size) != 0)
+ {
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s: verification of software breakpoint writing failed - trap opcodes not successfully read back after writing when setting breakpoint at 0x%" PRIx64, __FUNCTION__, addr);
+ return Error ("SoftwareBreakpoint::%s: verification of software breakpoint writing failed - trap opcodes not successfully read back after writing when setting breakpoint at 0x%" PRIx64, __FUNCTION__, addr);
+ }
+
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, addr);
+
+ return Error ();
+}
+
+// -------------------------------------------------------------------
+// instance-level members
+// -------------------------------------------------------------------
+
+SoftwareBreakpoint::SoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, const uint8_t *saved_opcodes, const uint8_t *trap_opcodes, size_t opcode_size) :
+ NativeBreakpoint (addr),
+ m_process (process),
+ m_saved_opcodes (),
+ m_trap_opcodes (),
+ m_opcode_size (opcode_size)
+{
+ assert ( opcode_size > 0 && "setting software breakpoint with no trap opcodes");
+ assert ( opcode_size <= MAX_TRAP_OPCODE_SIZE && "trap opcode size too large");
+
+ ::memcpy (m_saved_opcodes, saved_opcodes, opcode_size);
+ ::memcpy (m_trap_opcodes, trap_opcodes, opcode_size);
+}
+
+Error
+SoftwareBreakpoint::DoEnable ()
+{
+ return EnableSoftwareBreakpoint (m_process, m_addr, m_opcode_size, m_trap_opcodes, m_saved_opcodes);
+}
+
+Error
+SoftwareBreakpoint::DoDisable ()
+{
+ Error error;
+ assert (m_addr && (m_addr != LLDB_INVALID_ADDRESS) && "can't remove a software breakpoint for an invalid address");
+
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, m_addr);
+
+ assert ( (m_opcode_size > 0) && "cannot restore opcodes when there are no opcodes");
+
+ if (m_opcode_size > 0)
+ {
+ // Clear a software breakoint instruction
+ uint8_t curr_break_op [MAX_TRAP_OPCODE_SIZE];
+ bool break_op_found = false;
+ assert (m_opcode_size <= sizeof (curr_break_op));
+
+ // Read the breakpoint opcode
+ lldb::addr_t bytes_read = 0;
+ error = m_process.ReadMemory (m_addr, curr_break_op, m_opcode_size, bytes_read);
+ if (error.Success () && (bytes_read < static_cast<lldb::addr_t> (m_opcode_size)))
+ {
+ error.SetErrorStringWithFormat ("SoftwareBreakpointr::%s addr=0x%" PRIx64 ": tried to read %lu bytes but only read %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, bytes_read);
+ }
+ if (error.Success ())
+ {
+ bool verify = false;
+ // Make sure we have the a breakpoint opcode exists at this address
+ if (::memcmp (curr_break_op, m_trap_opcodes, m_opcode_size) == 0)
+ {
+ break_op_found = true;
+ // We found a valid breakpoint opcode at this address, now restore
+ // the saved opcode.
+ lldb::addr_t bytes_written = 0;
+ error = m_process.WriteMemory (m_addr, m_saved_opcodes, m_opcode_size, bytes_written);
+ if (error.Success () && (bytes_written < static_cast<lldb::addr_t> (m_opcode_size)))
+ {
+ error.SetErrorStringWithFormat ("SoftwareBreakpoint::%s addr=0x%" PRIx64 ": tried to write %lu bytes but only wrote %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, bytes_written);
+ }
+ if (error.Success ())
+ {
+ verify = true;
+ }
+ }
+ else
+ {
+ error.SetErrorString("Original breakpoint trap is no longer in memory.");
+ // Set verify to true and so we can check if the original opcode has already been restored
+ verify = true;
+ }
+
+ if (verify)
+ {
+ uint8_t verify_opcode [MAX_TRAP_OPCODE_SIZE];
+ assert (m_opcode_size <= sizeof (verify_opcode));
+ // Verify that our original opcode made it back to the inferior
+
+ lldb::addr_t verify_bytes_read = 0;
+ error = m_process.ReadMemory (m_addr, verify_opcode, m_opcode_size, verify_bytes_read);
+ if (error.Success () && (verify_bytes_read < static_cast<lldb::addr_t> (m_opcode_size)))
+ {
+ error.SetErrorStringWithFormat ("SoftwareBreakpoint::%s addr=0x%" PRIx64 ": tried to read %lu verification bytes but only read %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, verify_bytes_read);
+ }
+ if (error.Success ())
+ {
+ // compare the memory we just read with the original opcode
+ if (::memcmp (m_saved_opcodes, verify_opcode, m_opcode_size) == 0)
+ {
+ // SUCCESS
+ if (log)
+ log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, m_addr);
+ return error;
+ }
+ else
+ {
+ if (break_op_found)
+ error.SetErrorString("Failed to restore original opcode.");
+ }
+ }
+ else
+ error.SetErrorString("Failed to read memory to verify that breakpoint trap was restored.");
+ }
+ }
+ }
+
+ if (log && error.Fail ())
+ log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- FAILED: %s",
+ __FUNCTION__,
+ m_addr,
+ error.AsCString());
+ return error;
+}
+
+bool
+SoftwareBreakpoint::IsSoftwareBreakpoint () const
+{
+ return true;
+}
+
diff --git a/source/Host/common/SoftwareBreakpoint.h b/source/Host/common/SoftwareBreakpoint.h
new file mode 100644
index 000000000000..1fed19eca612
--- /dev/null
+++ b/source/Host/common/SoftwareBreakpoint.h
@@ -0,0 +1,51 @@
+//===-- SoftwareBreakpoint.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_SoftwareBreakpoint_h_
+#define liblldb_SoftwareBreakpoint_h_
+
+#include "lldb/lldb-private-forward.h"
+#include "NativeBreakpoint.h"
+
+namespace lldb_private
+{
+ class SoftwareBreakpoint : public NativeBreakpoint
+ {
+ public:
+ static Error
+ CreateSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint, NativeBreakpointSP &breakpoint_spn);
+
+ SoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, const uint8_t *saved_opcodes, const uint8_t *trap_opcodes, size_t opcode_size);
+
+ protected:
+ Error
+ DoEnable () override;
+
+ Error
+ DoDisable () override;
+
+ bool
+ IsSoftwareBreakpoint () const override;
+
+ private:
+ /// Max number of bytes that a software trap opcode sequence can occupy.
+ static const size_t MAX_TRAP_OPCODE_SIZE = 8;
+
+ NativeProcessProtocol &m_process;
+ uint8_t m_saved_opcodes [MAX_TRAP_OPCODE_SIZE];
+ uint8_t m_trap_opcodes [MAX_TRAP_OPCODE_SIZE];
+ const size_t m_opcode_size;
+
+ static Error
+ EnableSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t bp_opcode_size, const uint8_t *bp_opcode_bytes, uint8_t *saved_opcode_bytes);
+
+ };
+}
+
+#endif // #ifndef liblldb_SoftwareBreakpoint_h_
diff --git a/source/Host/common/Terminal.cpp b/source/Host/common/Terminal.cpp
index f63c468bb92c..ca46eb0f744b 100644
--- a/source/Host/common/Terminal.cpp
+++ b/source/Host/common/Terminal.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/Terminal.h"
+#include "llvm/ADT/STLExtras.h"
#include <fcntl.h>
#include <signal.h>
@@ -250,7 +251,7 @@ TerminalState::TTYStateIsValid() const
bool
TerminalState::ProcessGroupIsValid() const
{
- return m_process_group != -1;
+ return static_cast<int32_t>(m_process_group) != -1;
}
//------------------------------------------------------------------
@@ -274,7 +275,7 @@ TerminalStateSwitcher::~TerminalStateSwitcher ()
uint32_t
TerminalStateSwitcher::GetNumberOfStates() const
{
- return sizeof(m_ttystates)/sizeof(TerminalState);
+ return llvm::array_lengthof(m_ttystates);
}
//------------------------------------------------------------------
diff --git a/source/Host/freebsd/Host.cpp b/source/Host/freebsd/Host.cpp
index c4a6ca37e9c4..dc092e86d78b 100644
--- a/source/Host/freebsd/Host.cpp
+++ b/source/Host/freebsd/Host.cpp
@@ -13,7 +13,6 @@
#include <execinfo.h>
#include <sys/types.h>
#include <sys/user.h>
-#include <sys/utsname.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
@@ -27,6 +26,7 @@
#include "lldb/Core/Error.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/StreamFile.h"
@@ -39,8 +39,9 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Utility/CleanUp.h"
-#include "llvm/Support/Host.h"
+#include "Plugins/Process/Utility/FreeBSDSignals.h"
+#include "llvm/Support/Host.h"
extern "C" {
extern char **environ;
@@ -86,7 +87,40 @@ Host::ThreadCreated (const char *thread_name)
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;
}
@@ -134,56 +168,6 @@ Host::GetEnvironment (StringList &env)
return env.GetSize();
}
-bool
-Host::GetOSVersion(uint32_t &major,
- uint32_t &minor,
- uint32_t &update)
-{
- struct utsname un;
-
- ::memset(&un, 0, sizeof(utsname));
- if (uname(&un) < 0)
- return false;
-
- int status = sscanf(un.release, "%u.%u", &major, &minor);
- return status == 2;
-}
-
-bool
-Host::GetOSBuildString (std::string &s)
-{
- int mib[2] = { CTL_KERN, KERN_OSREV };
- char osrev_str[12];
- uint32_t osrev = 0;
- size_t osrev_len = sizeof(osrev);
-
- if (::sysctl (mib, 2, &osrev, &osrev_len, NULL, 0) == 0)
- {
- ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev);
- s.assign (osrev_str);
- return true;
- }
-
- s.clear();
- return false;
-}
-
-bool
-Host::GetOSKernelDescription (std::string &s)
-{
- struct utsname un;
-
- ::memset(&un, 0, sizeof(utsname));
- s.clear();
-
- if (uname(&un) < 0)
- return false;
-
- s.assign (un.version);
-
- return true;
-}
-
static bool
GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr,
ProcessInstanceInfo &process_info)
@@ -240,7 +224,7 @@ GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info)
{
if (process_info.ProcessIDIsValid())
{
- process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
+ process_info.GetArchitecture() = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
return true;
}
process_info.GetArchitecture().Clear();
@@ -306,9 +290,9 @@ Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstance
const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));
bool all_users = match_info.GetMatchAllUsers();
- const lldb::pid_t our_pid = getpid();
+ const ::pid_t our_pid = getpid();
const uid_t our_uid = getuid();
- for (int i = 0; i < actual_pid_count; i++)
+ for (size_t i = 0; i < actual_pid_count; i++)
{
const struct kinfo_proc &kinfo = kinfos[i];
const bool kinfo_user_matches = (all_users ||
@@ -418,3 +402,11 @@ Host::GetAuxvData(lldb_private::Process *process)
done:
return buf_sp;
}
+
+const UnixSignalsSP&
+Host::GetUnixSignals ()
+{
+ static const lldb_private::UnixSignalsSP s_unix_signals_sp (new FreeBSDSignals ());
+ return s_unix_signals_sp;
+}
+
diff --git a/source/Host/freebsd/HostInfoFreeBSD.cpp b/source/Host/freebsd/HostInfoFreeBSD.cpp
new file mode 100644
index 000000000000..78458259f0a2
--- /dev/null
+++ b/source/Host/freebsd/HostInfoFreeBSD.cpp
@@ -0,0 +1,85 @@
+//===-- HostInfoFreeBSD.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/freebsd/HostInfoFreeBSD.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/utsname.h>
+
+using namespace lldb_private;
+
+bool
+HostInfoFreeBSD::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update)
+{
+ struct utsname un;
+
+ ::memset(&un, 0, sizeof(utsname));
+ if (uname(&un) < 0)
+ return false;
+
+ int status = sscanf(un.release, "%u.%u", &major, &minor);
+ return status == 2;
+}
+
+bool
+HostInfoFreeBSD::GetOSBuildString(std::string &s)
+{
+ int mib[2] = {CTL_KERN, KERN_OSREV};
+ char osrev_str[12];
+ uint32_t osrev = 0;
+ size_t osrev_len = sizeof(osrev);
+
+ if (::sysctl(mib, 2, &osrev, &osrev_len, NULL, 0) == 0)
+ {
+ ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev);
+ s.assign(osrev_str);
+ return true;
+ }
+
+ s.clear();
+ return false;
+}
+
+bool
+HostInfoFreeBSD::GetOSKernelDescription(std::string &s)
+{
+ struct utsname un;
+
+ ::memset(&un, 0, sizeof(utsname));
+ s.clear();
+
+ if (uname(&un) < 0)
+ return false;
+
+ s.assign(un.version);
+
+ return true;
+}
+
+FileSpec
+HostInfoFreeBSD::GetProgramFileSpec()
+{
+ static FileSpec g_program_filespec;
+ if (!g_program_filespec)
+ {
+ int exe_path_mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid()};
+ size_t exe_path_size;
+ if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0)
+ {
+ char *exe_path = new char[exe_path_size];
+ if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0)
+ g_program_filespec.SetFile(exe_path, false);
+ delete[] exe_path;
+ }
+ }
+ return g_program_filespec;
+} \ No newline at end of file
diff --git a/source/Host/posix/FileSystem.cpp b/source/Host/posix/FileSystem.cpp
new file mode 100644
index 000000000000..571316811142
--- /dev/null
+++ b/source/Host/posix/FileSystem.cpp
@@ -0,0 +1,201 @@
+//===-- FileSystem.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/FileSystem.h"
+
+// C includes
+#include <sys/stat.h>
+#include <sys/types.h>
+
+// lldb Includes
+#include "lldb/Core/Error.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/Host.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+FileSpec::PathSyntax
+FileSystem::GetNativePathSyntax()
+{
+ return FileSpec::ePathSyntaxPosix;
+}
+
+Error
+FileSystem::MakeDirectory(const char *path, uint32_t file_permissions)
+{
+ Error error;
+ if (path && path[0])
+ {
+ if (::mkdir(path, file_permissions) != 0)
+ {
+ error.SetErrorToErrno();
+ switch (error.GetError())
+ {
+ case ENOENT:
+ {
+ // Parent directory doesn't exist, so lets make it if we can
+ FileSpec spec(path, false);
+ if (spec.GetDirectory() && spec.GetFilename())
+ {
+ // Make the parent directory and try again
+ Error error2 = MakeDirectory(spec.GetDirectory().GetCString(), file_permissions);
+ if (error2.Success())
+ {
+ // Try and make the directory again now that the parent directory was made successfully
+ if (::mkdir(path, file_permissions) == 0)
+ error.Clear();
+ else
+ error.SetErrorToErrno();
+ }
+ }
+ }
+ break;
+
+ case EEXIST:
+ {
+ FileSpec path_spec(path, false);
+ if (path_spec.IsDirectory())
+ error.Clear(); // It is a directory and it already exists
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("empty path");
+ }
+ return error;
+}
+
+Error
+FileSystem::DeleteDirectory(const char *path, bool recurse)
+{
+ Error error;
+ if (path && path[0])
+ {
+ if (recurse)
+ {
+ StreamString command;
+ command.Printf("rm -rf \"%s\"", path);
+ int status = ::system(command.GetString().c_str());
+ if (status != 0)
+ error.SetError(status, eErrorTypeGeneric);
+ }
+ else
+ {
+ if (::rmdir(path) != 0)
+ error.SetErrorToErrno();
+ }
+ }
+ else
+ {
+ error.SetErrorString("empty path");
+ }
+ return error;
+}
+
+Error
+FileSystem::GetFilePermissions(const char *path, uint32_t &file_permissions)
+{
+ Error error;
+ struct stat file_stats;
+ if (::stat(path, &file_stats) == 0)
+ {
+ // The bits in "st_mode" currently match the definitions
+ // for the file mode bits in unix.
+ file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ else
+ {
+ error.SetErrorToErrno();
+ }
+ return error;
+}
+
+Error
+FileSystem::SetFilePermissions(const char *path, uint32_t file_permissions)
+{
+ Error error;
+ if (::chmod(path, file_permissions) != 0)
+ error.SetErrorToErrno();
+ return error;
+}
+
+lldb::user_id_t
+FileSystem::GetFileSize(const FileSpec &file_spec)
+{
+ return file_spec.GetByteSize();
+}
+
+bool
+FileSystem::GetFileExists(const FileSpec &file_spec)
+{
+ return file_spec.Exists();
+}
+
+Error
+FileSystem::Symlink(const char *src, const char *dst)
+{
+ Error error;
+ if (::symlink(dst, src) == -1)
+ error.SetErrorToErrno();
+ return error;
+}
+
+Error
+FileSystem::Unlink(const char *path)
+{
+ Error error;
+ if (::unlink(path) == -1)
+ error.SetErrorToErrno();
+ return error;
+}
+
+Error
+FileSystem::Readlink(const char *path, char *buf, size_t buf_len)
+{
+ Error error;
+ ssize_t count = ::readlink(path, buf, buf_len);
+ if (count < 0)
+ error.SetErrorToErrno();
+ else if (static_cast<size_t>(count) < (buf_len - 1))
+ buf[count] = '\0'; // Success
+ else
+ error.SetErrorString("'buf' buffer is too small to contain link contents");
+ return error;
+}
+
+bool
+FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high)
+{
+#if defined(__APPLE__)
+ StreamString md5_cmd_line;
+ md5_cmd_line.Printf("md5 -q '%s'", file_spec.GetPath().c_str());
+ std::string hash_string;
+ Error err = Host::RunShellCommand(md5_cmd_line.GetData(), NULL, NULL, NULL, &hash_string, 60);
+ if (err.Fail())
+ return false;
+ // a correctly formed MD5 is 16-bytes, that is 32 hex digits
+ // if the output is any other length it is probably wrong
+ if (hash_string.size() != 32)
+ return false;
+ std::string part1(hash_string, 0, 16);
+ std::string part2(hash_string, 16);
+ const char *part1_cstr = part1.c_str();
+ const char *part2_cstr = part2.c_str();
+ high = ::strtoull(part1_cstr, NULL, 16);
+ low = ::strtoull(part2_cstr, NULL, 16);
+ return true;
+#else
+ // your own MD5 implementation here
+ return false;
+#endif
+}
diff --git a/source/Host/posix/HostInfoPosix.cpp b/source/Host/posix/HostInfoPosix.cpp
new file mode 100644
index 000000000000..77fdc2b61a31
--- /dev/null
+++ b/source/Host/posix/HostInfoPosix.cpp
@@ -0,0 +1,193 @@
+//===-- HostInfoPosix.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/Core/Log.h"
+#include "lldb/Host/posix/HostInfoPosix.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <grp.h>
+#include <limits.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+using namespace lldb_private;
+
+size_t
+HostInfoPosix::GetPageSize()
+{
+ return ::getpagesize();
+}
+
+bool
+HostInfoPosix::GetHostname(std::string &s)
+{
+ char hostname[PATH_MAX];
+ hostname[sizeof(hostname) - 1] = '\0';
+ if (::gethostname(hostname, sizeof(hostname) - 1) == 0)
+ {
+ struct hostent *h = ::gethostbyname(hostname);
+ if (h)
+ s.assign(h->h_name);
+ else
+ s.assign(hostname);
+ return true;
+ }
+ return false;
+}
+
+const char *
+HostInfoPosix::LookupUserName(uint32_t uid, std::string &user_name)
+{
+ struct passwd user_info;
+ struct passwd *user_info_ptr = &user_info;
+ char user_buffer[PATH_MAX];
+ size_t user_buffer_size = sizeof(user_buffer);
+ if (::getpwuid_r(uid, &user_info, user_buffer, user_buffer_size, &user_info_ptr) == 0)
+ {
+ if (user_info_ptr)
+ {
+ user_name.assign(user_info_ptr->pw_name);
+ return user_name.c_str();
+ }
+ }
+ user_name.clear();
+ return NULL;
+}
+
+const char *
+HostInfoPosix::LookupGroupName(uint32_t gid, std::string &group_name)
+{
+ char group_buffer[PATH_MAX];
+ size_t group_buffer_size = sizeof(group_buffer);
+ struct group group_info;
+ struct group *group_info_ptr = &group_info;
+ // Try the threadsafe version first
+ if (::getgrgid_r(gid, &group_info, group_buffer, group_buffer_size, &group_info_ptr) == 0)
+ {
+ if (group_info_ptr)
+ {
+ group_name.assign(group_info_ptr->gr_name);
+ return group_name.c_str();
+ }
+ }
+ else
+ {
+ // The threadsafe version isn't currently working for me on darwin, but the non-threadsafe version
+ // is, so I am calling it below.
+ group_info_ptr = ::getgrgid(gid);
+ if (group_info_ptr)
+ {
+ group_name.assign(group_info_ptr->gr_name);
+ return group_name.c_str();
+ }
+ }
+ group_name.clear();
+ return NULL;
+}
+
+uint32_t
+HostInfoPosix::GetUserID()
+{
+ return getuid();
+}
+
+uint32_t
+HostInfoPosix::GetGroupID()
+{
+ return getgid();
+}
+
+uint32_t
+HostInfoPosix::GetEffectiveUserID()
+{
+ return geteuid();
+}
+
+uint32_t
+HostInfoPosix::GetEffectiveGroupID()
+{
+ return getegid();
+}
+
+bool
+HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec)
+{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+
+ FileSpec lldb_file_spec;
+ if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
+ return false;
+
+ char raw_path[PATH_MAX];
+ lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
+
+ // Most Posix systems (e.g. Linux/*BSD) will attempt to replace a */lib with */bin as the base
+ // directory for helper exe programs. This will fail if the /lib and /bin directories are
+ // rooted in entirely different trees.
+ if (log)
+ log->Printf("HostInfoPosix::ComputeSupportExeDirectory() attempting to derive the bin path (ePathTypeSupportExecutableDir) from "
+ "this path: %s",
+ raw_path);
+ char *lib_pos = ::strstr(raw_path, "/lib");
+ if (lib_pos != nullptr)
+ {
+ // First terminate the raw path at the start of lib.
+ *lib_pos = '\0';
+
+ // Now write in bin in place of lib.
+ ::strncpy(lib_pos, "/bin", PATH_MAX - (lib_pos - raw_path));
+
+ if (log)
+ log->Printf("Host::%s() derived the bin path as: %s", __FUNCTION__, raw_path);
+ }
+ else
+ {
+ if (log)
+ log->Printf("Host::%s() failed to find /lib/liblldb within the shared lib path, bailing on bin path construction",
+ __FUNCTION__);
+ }
+ file_spec.GetDirectory().SetCString(raw_path);
+ return (bool)file_spec.GetDirectory();
+}
+
+bool
+HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec)
+{
+ FileSpec temp_file("/opt/local/include/lldb", false);
+ file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
+ return true;
+}
+
+bool
+HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec)
+{
+ FileSpec lldb_file_spec;
+ if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
+ return false;
+
+ char raw_path[PATH_MAX];
+ lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
+
+ llvm::SmallString<256> python_version_dir;
+ llvm::raw_svector_ostream os(python_version_dir);
+ os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION << "/site-packages";
+ os.flush();
+
+ // We may get our string truncated. Should we protect this with an assert?
+ ::strncat(raw_path, python_version_dir.c_str(), sizeof(raw_path) - strlen(raw_path) - 1);
+
+ file_spec.GetDirectory().SetCString(raw_path);
+ return true;
+}
diff --git a/source/Host/posix/HostProcessPosix.cpp b/source/Host/posix/HostProcessPosix.cpp
new file mode 100644
index 000000000000..4618de4711de
--- /dev/null
+++ b/source/Host/posix/HostProcessPosix.cpp
@@ -0,0 +1,103 @@
+//===-- HostProcessWindows.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/HostProcessPosix.h"
+#include "lldb/Host/FileSystem.h"
+
+#include "llvm/ADT/STLExtras.h"
+
+#include <limits.h>
+
+using namespace lldb_private;
+
+const lldb::pid_t HostProcessPosix::kInvalidProcessId = 0;
+
+HostProcessPosix::HostProcessPosix()
+: m_pid(kInvalidProcessId)
+{
+}
+
+HostProcessPosix::~HostProcessPosix()
+{
+}
+
+Error HostProcessPosix::Create(lldb::pid_t pid)
+{
+ 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)
+ {
+ Error error;
+ error.SetErrorString("HostProcessPosix refers to an invalid process");
+ return error;
+ }
+
+ return HostProcessPosix::Signal(m_pid, signo);
+}
+
+Error HostProcessPosix::Signal(lldb::pid_t pid, int signo)
+{
+ Error error;
+
+ if (-1 == ::kill(pid, signo))
+ error.SetErrorToErrno();
+
+ return error;
+}
+
+Error HostProcessPosix::GetMainModule(FileSpec &file_spec) const
+{
+ Error error;
+
+ // 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)
+ {
+ error.SetErrorString("Unable to build /proc/<pid>/exe string");
+ return error;
+ }
+
+ error = FileSystem::Readlink(link_path, exe_path, llvm::array_lengthof(exe_path));
+ if (!error.Success())
+ return error;
+
+ const ssize_t len = strlen(exe_path);
+ // If the binary has been deleted, the link name has " (deleted)" appended.
+ // Remove if there.
+ static const ssize_t deleted_len = strlen(" (deleted)");
+ if (len > deleted_len &&
+ !strcmp(exe_path + len - deleted_len, " (deleted)"))
+ {
+ exe_path[len - deleted_len] = 0;
+ }
+
+ file_spec.SetFile(exe_path, false);
+ return error;
+}
+
+lldb::pid_t HostProcessPosix::GetProcessId() const
+{
+ return m_pid;
+}
+
+bool HostProcessPosix::IsRunning() const
+{
+ // Send this process the null signal. If it succeeds the process is running.
+ Error error = Signal(0);
+ return error.Success();
+}
diff --git a/source/Interpreter/Args.cpp b/source/Interpreter/Args.cpp
index b6f34fd1f7fb..4831eaaac348 100644
--- a/source/Interpreter/Args.cpp
+++ b/source/Interpreter/Args.cpp
@@ -20,6 +20,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Interpreter/Options.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Process.h"
//#include "lldb/Target/RegisterContext.h"
@@ -166,7 +167,7 @@ Args::SetCommandString (const char *command)
{
static const char *k_space_separators = " \t";
static const char *k_space_separators_with_slash_and_quotes = " \t \\'\"";
- const char *arg_end = NULL;
+ const char *arg_end = nullptr;
const char *arg_pos;
for (arg_pos = command;
arg_pos && arg_pos[0];
@@ -371,7 +372,7 @@ Args::UpdateArgsAfterOptionParsing()
++argv_pos)
{
const char *argv_cstr = *argv_pos;
- if (argv_cstr == NULL)
+ if (argv_cstr == nullptr)
break;
while (args_pos != m_args.end())
@@ -407,7 +408,7 @@ Args::UpdateArgvFromArgs()
arg_sstr_collection::const_iterator pos, end = m_args.end();
for (pos = m_args.begin(); pos != end; ++pos)
m_argv.push_back(pos->c_str());
- m_argv.push_back(NULL);
+ m_argv.push_back(nullptr);
// Make sure we have enough arg quote chars in the array
if (m_args_quote_char.size() < m_args.size())
m_args_quote_char.resize (m_argv.size());
@@ -426,7 +427,7 @@ Args::GetArgumentAtIndex (size_t idx) const
{
if (idx < m_argv.size())
return m_argv[idx];
- return NULL;
+ return nullptr;
}
char
@@ -442,7 +443,7 @@ Args::GetArgumentVector()
{
if (!m_argv.empty())
return (char **)&m_argv[0];
- return NULL;
+ return nullptr;
}
const char **
@@ -450,7 +451,7 @@ Args::GetConstArgumentVector() const
{
if (!m_argv.empty())
return (const char **)&m_argv[0];
- return NULL;
+ return nullptr;
}
void
@@ -545,7 +546,7 @@ Args::ReplaceArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
m_args_quote_char[idx] = quote_char;
return GetArgumentAtIndex(idx);
}
- return NULL;
+ return nullptr;
}
void
@@ -621,20 +622,20 @@ Args::ParseOptions (Options &options)
StreamString sstr;
Error error;
Option *long_options = options.GetLongOptions();
- if (long_options == NULL)
+ if (long_options == nullptr)
{
error.SetErrorStringWithFormat("invalid long options");
return error;
}
- for (int i=0; long_options[i].name != NULL; ++i)
+ for (int i=0; long_options[i].definition != nullptr; ++i)
{
- if (long_options[i].flag == NULL)
+ if (long_options[i].flag == nullptr)
{
if (isprint8(long_options[i].val))
{
sstr << (char)long_options[i].val;
- switch (long_options[i].has_arg)
+ switch (long_options[i].definition->option_has_arg)
{
default:
case OptionParser::eNoArgument: break;
@@ -673,7 +674,7 @@ Args::ParseOptions (Options &options)
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;
+ long_options[i].definition || long_options[i].flag || long_options[i].val;
++i)
{
if (long_options[i].val == val)
@@ -686,8 +687,18 @@ Args::ParseOptions (Options &options)
// Call the callback with the option
if (long_options_index >= 0)
{
- error = options.SetOptionValue(long_options_index,
- long_options[long_options_index].has_arg == OptionParser::eNoArgument ? NULL : OptionParser::GetOptionArgument());
+ const OptionDefinition *def = long_options[long_options_index].definition;
+ CommandInterpreter &interpreter = options.GetInterpreter();
+ OptionValidator *validator = def->validator;
+ if (validator && !validator->IsValid(*interpreter.GetPlatform(true), interpreter.GetExecutionContext()))
+ {
+ error.SetErrorStringWithFormat("Option \"%s\" invalid. %s", def->long_option, def->validator->LongConditionString());
+ }
+ else
+ {
+ error = options.SetOptionValue(long_options_index,
+ (def->option_has_arg == OptionParser::eNoArgument) ? nullptr : OptionParser::GetOptionArgument());
+ }
}
else
{
@@ -716,7 +727,7 @@ Args::StringToSInt32 (const char *s, int32_t fail_value, int base, bool *success
{
if (s && s[0])
{
- char *end = NULL;
+ char *end = nullptr;
const long sval = ::strtol (s, &end, base);
if (*end == '\0')
{
@@ -734,7 +745,7 @@ Args::StringToUInt32 (const char *s, uint32_t fail_value, int base, bool *succes
{
if (s && s[0])
{
- char *end = NULL;
+ char *end = nullptr;
const unsigned long uval = ::strtoul (s, &end, base);
if (*end == '\0')
{
@@ -753,7 +764,7 @@ Args::StringToSInt64 (const char *s, int64_t fail_value, int base, bool *success
{
if (s && s[0])
{
- char *end = NULL;
+ char *end = nullptr;
int64_t uval = ::strtoll (s, &end, base);
if (*end == '\0')
{
@@ -770,7 +781,7 @@ Args::StringToUInt64 (const char *s, uint64_t fail_value, int base, bool *succes
{
if (s && s[0])
{
- char *end = NULL;
+ char *end = nullptr;
uint64_t uval = ::strtoull (s, &end, base);
if (*end == '\0')
{
@@ -788,7 +799,7 @@ Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::add
bool error_set = false;
if (s && s[0])
{
- char *end = NULL;
+ char *end = nullptr;
lldb::addr_t addr = ::strtoull (s, &end, 0);
if (*end == '\0')
{
@@ -817,13 +828,13 @@ Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::add
options.SetKeepInMemory(false);
options.SetTryAllThreads(true);
- ExecutionResults expr_result = target->EvaluateExpression(s,
+ ExpressionResults expr_result = target->EvaluateExpression(s,
exe_ctx->GetFramePtr(),
valobj_sp,
options);
bool success = false;
- if (expr_result == eExecutionCompleted)
+ if (expr_result == eExpressionCompleted)
{
// Get the address to watch.
addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
@@ -923,7 +934,7 @@ Args::StripSpaces (std::string &s, bool leading, bool trailing, bool return_null
}
}
if (return_null_if_empty && s.empty())
- return NULL;
+ return nullptr;
return s.c_str();
}
@@ -964,7 +975,7 @@ Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t
if (s && s[0])
{
- char *pos = NULL;
+ char *pos = nullptr;
unsigned long uval32 = ::strtoul (s, &pos, 0);
if (pos == s)
return s;
@@ -991,7 +1002,7 @@ Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t
return pos;
}
}
- return 0;
+ return nullptr;
}
const char *
@@ -1022,7 +1033,7 @@ Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, in
{
if (s && s[0])
{
- for (int i = 0; enum_values[i].string_value != NULL ; i++)
+ for (int i = 0; enum_values[i].string_value != nullptr ; i++)
{
if (strstr(enum_values[i].string_value, s) == enum_values[i].string_value)
{
@@ -1034,7 +1045,7 @@ Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, in
StreamString strm;
strm.PutCString ("invalid enumeration value, valid values are: ");
- for (int i = 0; enum_values[i].string_value != NULL; i++)
+ for (int i = 0; enum_values[i].string_value != nullptr; i++)
{
strm.Printf ("%s\"%s\"",
i > 0 ? ", " : "",
@@ -1087,7 +1098,7 @@ Args::StringToFormat
{
if (isdigit (s[0]))
{
- char *format_char = NULL;
+ char *format_char = nullptr;
unsigned long byte_size = ::strtoul (s, &format_char, 0);
if (byte_size != ULONG_MAX)
*byte_size_ptr = byte_size;
@@ -1155,7 +1166,7 @@ Args::StringToGenericRegister (const char *s)
return LLDB_REGNUM_GENERIC_SP;
else if (strcmp(s, "fp") == 0)
return LLDB_REGNUM_GENERIC_FP;
- else if (strcmp(s, "ra") == 0)
+ else if (strcmp(s, "ra") == 0 || strcmp(s, "lr") == 0)
return LLDB_REGNUM_GENERIC_RA;
else if (strcmp(s, "flags") == 0)
return LLDB_REGNUM_GENERIC_FLAGS;
@@ -1222,7 +1233,7 @@ Args::FindArgumentIndexForOption (Option *long_options, int long_options_index)
char short_buffer[3];
char long_buffer[255];
::snprintf (short_buffer, sizeof (short_buffer), "-%c", long_options[long_options_index].val);
- ::snprintf (long_buffer, sizeof (long_buffer), "--%s", long_options[long_options_index].name);
+ ::snprintf (long_buffer, sizeof (long_buffer), "--%s", long_options[long_options_index].definition->long_option);
size_t end = GetArgumentCount ();
size_t idx = 0;
while (idx < end)
@@ -1241,7 +1252,7 @@ Args::FindArgumentIndexForOption (Option *long_options, int long_options_index)
bool
Args::IsPositionalArgument (const char *arg)
{
- if (arg == NULL)
+ if (arg == nullptr)
return false;
bool is_positional = true;
@@ -1271,19 +1282,19 @@ Args::ParseAliasOptions (Options &options,
int i;
Option *long_options = options.GetLongOptions();
- if (long_options == NULL)
+ if (long_options == nullptr)
{
result.AppendError ("invalid long options");
result.SetStatus (eReturnStatusFailed);
return;
}
- for (i = 0; long_options[i].name != NULL; ++i)
+ for (i = 0; long_options[i].definition != nullptr; ++i)
{
- if (long_options[i].flag == NULL)
+ if (long_options[i].flag == nullptr)
{
sstr << (char) long_options[i].val;
- switch (long_options[i].has_arg)
+ switch (long_options[i].definition->option_has_arg)
{
default:
case OptionParser::eNoArgument:
@@ -1322,13 +1333,13 @@ Args::ParseAliasOptions (Options &options,
if (val == 0)
continue;
- ((Options *) &options)->OptionSeen (val);
+ options.OptionSeen (val);
// Look up the long option index
if (long_options_index == -1)
{
for (int j = 0;
- long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
+ long_options[j].definition || long_options[j].flag || long_options[j].val;
++j)
{
if (long_options[j].val == val)
@@ -1344,8 +1355,10 @@ Args::ParseAliasOptions (Options &options,
{
StreamString option_str;
option_str.Printf ("-%c", val);
+ const OptionDefinition *def = long_options[long_options_index].definition;
+ int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
- switch (long_options[long_options_index].has_arg)
+ switch (has_arg)
{
case OptionParser::eNoArgument:
option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
@@ -1353,7 +1366,7 @@ Args::ParseAliasOptions (Options &options,
result.SetStatus (eReturnStatusSuccessFinishNoResult);
break;
case OptionParser::eRequiredArgument:
- if (OptionParser::GetOptionArgument() != NULL)
+ if (OptionParser::GetOptionArgument() != nullptr)
{
option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
OptionArgValue (OptionParser::eRequiredArgument,
@@ -1368,7 +1381,7 @@ Args::ParseAliasOptions (Options &options,
}
break;
case OptionParser::eOptionalArgument:
- if (OptionParser::GetOptionArgument() != NULL)
+ if (OptionParser::GetOptionArgument() != nullptr)
{
option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
OptionArgValue (OptionParser::eOptionalArgument,
@@ -1410,8 +1423,8 @@ Args::ParseAliasOptions (Options &options,
raw_input_string.erase (pos, strlen (tmp_arg));
}
ReplaceArgumentAtIndex (idx, "");
- if ((long_options[long_options_index].has_arg != OptionParser::eNoArgument)
- && (OptionParser::GetOptionArgument() != NULL)
+ if ((long_options[long_options_index].definition->option_has_arg != OptionParser::eNoArgument)
+ && (OptionParser::GetOptionArgument() != nullptr)
&& (idx+1 < GetArgumentCount())
&& (strcmp (OptionParser::GetOptionArgument(), GetArgumentAtIndex(idx+1)) == 0))
{
@@ -1444,7 +1457,7 @@ Args::ParseArgsForCompletion
Option *long_options = options.GetLongOptions();
option_element_vector.clear();
- if (long_options == NULL)
+ if (long_options == nullptr)
{
return;
}
@@ -1453,12 +1466,12 @@ Args::ParseArgsForCompletion
// to suppress error messages.
sstr << ":";
- for (int i = 0; long_options[i].name != NULL; ++i)
+ for (int i = 0; long_options[i].definition != nullptr; ++i)
{
- if (long_options[i].flag == NULL)
+ if (long_options[i].flag == nullptr)
{
sstr << (char) long_options[i].val;
- switch (long_options[i].has_arg)
+ switch (long_options[i].definition->option_has_arg)
{
default:
case OptionParser::eNoArgument:
@@ -1516,11 +1529,11 @@ Args::ParseArgsForCompletion
// were passed. This will be useful when we come to restricting completions based on what other
// options we've seen on the line.
- if (OptionParser::GetOptionIndex() < dummy_vec.size() - 1
+ if (static_cast<size_t>(OptionParser::GetOptionIndex()) < dummy_vec.size() - 1
&& (strcmp (dummy_vec[OptionParser::GetOptionIndex()-1], "--") == 0))
{
dash_dash_pos = OptionParser::GetOptionIndex() - 1;
- if (OptionParser::GetOptionIndex() - 1 == cursor_index)
+ if (static_cast<size_t>(OptionParser::GetOptionIndex() - 1) == cursor_index)
{
option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, OptionParser::GetOptionIndex() - 1,
OptionArgElement::eBareDoubleDash));
@@ -1555,7 +1568,7 @@ Args::ParseArgsForCompletion
if (long_options_index == -1)
{
for (int j = 0;
- long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
+ long_options[j].definition || long_options[j].flag || long_options[j].val;
++j)
{
if (long_options[j].val == val)
@@ -1581,13 +1594,15 @@ Args::ParseArgsForCompletion
}
}
- switch (long_options[long_options_index].has_arg)
+ const OptionDefinition *def = long_options[long_options_index].definition;
+ int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
+ switch (has_arg)
{
case OptionParser::eNoArgument:
option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));
break;
case OptionParser::eRequiredArgument:
- if (OptionParser::GetOptionArgument() != NULL)
+ if (OptionParser::GetOptionArgument() != nullptr)
{
int arg_index;
if (missing_argument)
@@ -1603,7 +1618,7 @@ Args::ParseArgsForCompletion
}
break;
case OptionParser::eOptionalArgument:
- if (OptionParser::GetOptionArgument() != NULL)
+ if (OptionParser::GetOptionArgument() != nullptr)
{
option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1));
}
@@ -1629,8 +1644,10 @@ Args::ParseArgsForCompletion
// Finally we have to handle the case where the cursor index points at a single "-". We want to mark that in
// the option_element_vector, but only if it is not after the "--". But it turns out that OptionParser::Parse just ignores
// an isolated "-". So we have to look it up by hand here. We only care if it is AT the cursor position.
+ // Note, a single quoted dash is not the same as a single dash...
- if ((dash_dash_pos == -1 || cursor_index < dash_dash_pos)
+ if ((static_cast<int32_t>(dash_dash_pos) == -1 || cursor_index < dash_dash_pos)
+ && m_args_quote_char[cursor_index] == '\0'
&& strcmp (GetArgumentAtIndex(cursor_index), "-") == 0)
{
option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDash, cursor_index,
@@ -1686,7 +1703,7 @@ Args::EncodeEscapeSequences (const char *src, std::string &dst)
// the main for loop will do this for us, so we advance p by
// one less than i (even if i is zero)
p += i - 1;
- unsigned long octal_value = ::strtoul (oct_str, NULL, 8);
+ unsigned long octal_value = ::strtoul (oct_str, nullptr, 8);
if (octal_value <= UINT8_MAX)
{
dst.append(1, (char)octal_value);
@@ -1709,7 +1726,7 @@ Args::EncodeEscapeSequences (const char *src, std::string &dst)
hex_str[1] = *p;
}
- unsigned long hex_value = strtoul (hex_str, NULL, 16);
+ unsigned long hex_value = strtoul (hex_str, nullptr, 16);
if (hex_value <= UINT8_MAX)
dst.append (1, (char)hex_value);
}
diff --git a/source/Interpreter/CommandHistory.cpp b/source/Interpreter/CommandHistory.cpp
index 33971e3959c6..26996a625642 100644
--- a/source/Interpreter/CommandHistory.cpp
+++ b/source/Interpreter/CommandHistory.cpp
@@ -41,17 +41,17 @@ CommandHistory::FindString (const char* input_str) const
{
Mutex::Locker locker(m_mutex);
if (!input_str)
- return NULL;
+ return nullptr;
if (input_str[0] != g_repeat_char)
- return NULL;
+ return nullptr;
if (input_str[1] == '-')
{
bool success;
size_t idx = Args::StringToUInt32 (input_str+2, 0, 0, &success);
if (!success)
- return NULL;
+ return nullptr;
if (idx > m_history.size())
- return NULL;
+ return nullptr;
idx = m_history.size() - idx;
return m_history[idx].c_str();
@@ -59,7 +59,7 @@ CommandHistory::FindString (const char* input_str) const
else if (input_str[1] == g_repeat_char)
{
if (m_history.empty())
- return NULL;
+ return nullptr;
else
return m_history.back().c_str();
}
@@ -68,9 +68,9 @@ CommandHistory::FindString (const char* input_str) const
bool success;
uint32_t idx = Args::StringToUInt32 (input_str+1, 0, 0, &success);
if (!success)
- return NULL;
+ return nullptr;
if (idx >= m_history.size())
- return NULL;
+ return nullptr;
return m_history[idx].c_str();
}
}
@@ -81,7 +81,7 @@ CommandHistory::GetStringAtIndex (size_t idx) const
Mutex::Locker locker(m_mutex);
if (idx < m_history.size())
return m_history[idx].c_str();
- return NULL;
+ return nullptr;
}
const char*
@@ -95,7 +95,7 @@ CommandHistory::GetRecentmostString () const
{
Mutex::Locker locker(m_mutex);
if (m_history.empty())
- return NULL;
+ return nullptr;
return m_history.back().c_str();
}
@@ -137,7 +137,7 @@ CommandHistory::Dump (Stream& stream,
if (!hist_item.empty())
{
stream.Indent();
- stream.Printf ("%4zu: %s\n", counter, hist_item.c_str());
+ stream.Printf("%4" PRIu64 ": %s\n", (uint64_t)counter, hist_item.c_str());
}
}
}
diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp
index fb0fc7f700a5..56c8f8c0ad6a 100644
--- a/source/Interpreter/CommandInterpreter.cpp
+++ b/source/Interpreter/CommandInterpreter.cpp
@@ -44,12 +44,14 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Timer.h"
#include "lldb/Host/Editline.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandCompletions.h"
@@ -66,6 +68,10 @@
#include "lldb/Utility/CleanUp.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Path.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -73,10 +79,10 @@ using namespace lldb_private;
static PropertyDefinition
g_properties[] =
{
- { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." },
- { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." },
- { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will stop running a 'command source' script upon encountering an error." },
- { NULL , OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL }
+ { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." },
+ { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." },
+ { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will stop running a 'command source' script upon encountering an error." },
+ { nullptr , OptionValue::eTypeInvalid, true, 0 , nullptr, nullptr, nullptr }
};
enum
@@ -125,21 +131,21 @@ bool
CommandInterpreter::GetExpandRegexAliases () const
{
const uint32_t idx = ePropertyExpandRegexAliases;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
}
bool
CommandInterpreter::GetPromptOnQuit () const
{
const uint32_t idx = ePropertyPromptOnQuit;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
}
bool
CommandInterpreter::GetStopCmdSourceOnError () const
{
const uint32_t idx = ePropertyStopCmdSourceOnError;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
}
void
@@ -324,7 +330,7 @@ CommandInterpreter::Initialize ()
if (cmd_obj_sp)
{
alias_arguments_vector_sp.reset (new OptionArgVector);
-#if defined (__arm__)
+#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);
@@ -351,6 +357,15 @@ CommandInterpreter::Initialize ()
}
}
+void
+CommandInterpreter::Clear()
+{
+ m_command_io_handler_sp.reset();
+
+ if (m_script_interpreter_ap)
+ m_script_interpreter_ap->Clear();
+}
+
const char *
CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)
{
@@ -405,9 +420,9 @@ CommandInterpreter::LoadCommandDictionary ()
{"^(-.*)$", "breakpoint set %1"},
{"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"},
{"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"},
- {"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}};
+ {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}};
- size_t num_regexes = sizeof break_regexes/sizeof(char *[2]);
+ size_t num_regexes = llvm::array_lengthof(break_regexes);
std::unique_ptr<CommandObjectRegexCommand>
break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
@@ -702,7 +717,7 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
StringList local_matches;
- if (matches == NULL)
+ if (matches == nullptr)
matches = &local_matches;
unsigned int num_cmd_matches = 0;
@@ -830,17 +845,17 @@ CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliase
Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command.
CommandObjectSP ret_val; // Possibly empty return value.
- if (cmd_cstr == NULL)
+ if (cmd_cstr == nullptr)
return ret_val;
if (cmd_words.GetArgumentCount() == 1)
- return GetCommandSP(cmd_cstr, include_aliases, true, NULL);
+ return GetCommandSP(cmd_cstr, include_aliases, true, nullptr);
else
{
// We have a multi-word command (seemingly), so we need to do more work.
// First, get the cmd_obj_sp for the first word in the command.
- CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, NULL);
- if (cmd_obj_sp.get() != NULL)
+ CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, nullptr);
+ if (cmd_obj_sp.get() != nullptr)
{
// Loop through the rest of the words in the command (everything passed in was supposed to be part of a
// command name), and find the appropriate sub-command SP for each command word....
@@ -850,7 +865,7 @@ CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliase
if (cmd_obj_sp->IsMultiwordObject())
{
cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j));
- if (cmd_obj_sp.get() == NULL)
+ if (cmd_obj_sp.get() == nullptr)
// The sub-command name was invalid. Fail and return the empty 'ret_val'.
return ret_val;
}
@@ -890,7 +905,7 @@ CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
return command_obj;
// If there wasn't an exact match then look for an inexact one in just the commands
- command_obj = GetCommandSP(cmd_cstr, false, false, NULL).get();
+ command_obj = GetCommandSP(cmd_cstr, false, false, nullptr).get();
// Finally, if there wasn't an inexact match among the commands, look for an inexact
// match in both the commands and aliases.
@@ -1156,7 +1171,7 @@ CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
// This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
// eventually be invoked by the given command line.
- CommandObject *cmd_obj = NULL;
+ CommandObject *cmd_obj = nullptr;
std::string white_space (" \t\v");
size_t start = command_string.find_first_not_of (white_space);
size_t end = 0;
@@ -1171,7 +1186,7 @@ CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
end = command_string.size();
std::string cmd_word = command_string.substr (start, end - start);
- if (cmd_obj == NULL)
+ if (cmd_obj == nullptr)
// Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
// command or alias.
cmd_obj = GetCommandObject (cmd_word.c_str());
@@ -1325,7 +1340,7 @@ CommandInterpreter::BuildAliasResult (const char *alias_name,
std::string &alias_result,
CommandReturnObject &result)
{
- CommandObject *alias_cmd_obj = NULL;
+ CommandObject *alias_cmd_obj = nullptr;
Args cmd_args (raw_input_string.c_str());
alias_cmd_obj = GetCommandObject (alias_name);
StreamString result_str;
@@ -1363,7 +1378,7 @@ CommandInterpreter::BuildAliasResult (const char *alias_name,
int index = GetOptionArgumentPosition (value.c_str());
if (index == 0)
result_str.Printf ("%s", value.c_str());
- else if (index >= cmd_args.GetArgumentCount())
+ else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount())
{
result.AppendErrorWithFormat
@@ -1446,12 +1461,12 @@ CommandInterpreter::PreprocessCommand (std::string &command)
options.SetTryAllThreads(true);
options.SetTimeoutUsec(0);
- ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
+ ExpressionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
exe_ctx.GetFramePtr(),
expr_result_valobj_sp,
options);
- if (expr_result == eExecutionCompleted)
+ if (expr_result == eExpressionCompleted)
{
Scalar scalar;
if (expr_result_valobj_sp->ResolveValue (scalar))
@@ -1486,24 +1501,29 @@ CommandInterpreter::PreprocessCommand (std::string &command)
switch (expr_result)
{
- case eExecutionSetupError:
+ case eExpressionSetupError:
error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
break;
- case eExecutionCompleted:
+ case eExpressionParseError:
+ error.SetErrorStringWithFormat ("expression parse error for the expression '%s'", expr_str.c_str());
+ break;
+ case eExpressionResultUnavailable:
+ error.SetErrorStringWithFormat ("expression error fetching result for the expression '%s'", expr_str.c_str());
+ case eExpressionCompleted:
break;
- case eExecutionDiscarded:
+ case eExpressionDiscarded:
error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
break;
- case eExecutionInterrupted:
+ case eExpressionInterrupted:
error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
break;
- case eExecutionHitBreakpoint:
+ case eExpressionHitBreakpoint:
error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
break;
- case eExecutionTimedOut:
+ case eExpressionTimedOut:
error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
break;
- case eExecutionStoppedForDebug:
+ case eExpressionStoppedForDebug:
error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str());
break;
}
@@ -1530,7 +1550,7 @@ CommandInterpreter::HandleCommand (const char *command_line,
{
bool done = false;
- CommandObject *cmd_obj = NULL;
+ CommandObject *cmd_obj = nullptr;
bool wants_raw_input = false;
std::string command_string (command_line);
std::string original_command_string (command_line);
@@ -1540,7 +1560,7 @@ CommandInterpreter::HandleCommand (const char *command_line,
// Make a scoped cleanup object that will clear the crash description string
// on exit of this function.
- lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription);
+ lldb_utility::CleanUp <const char *> crash_description_cleanup(nullptr, Host::SetCrashDescription);
if (log)
log->Printf ("Processing command: %s", command_line);
@@ -1574,7 +1594,7 @@ CommandInterpreter::HandleCommand (const char *command_line,
else if (command_string[non_space] == CommandHistory::g_repeat_char)
{
const char *history_string = m_command_history.FindString(command_string.c_str() + non_space);
- if (history_string == NULL)
+ if (history_string == nullptr)
{
result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
result.SetStatus(eReturnStatusFailed);
@@ -1650,7 +1670,7 @@ CommandInterpreter::HandleCommand (const char *command_line,
char quote_char = '\0';
std::string suffix;
ExtractCommand (command_string, next_word, suffix, quote_char);
- if (cmd_obj == NULL)
+ if (cmd_obj == nullptr)
{
std::string full_name;
if (GetAliasFullName(next_word.c_str(), full_name))
@@ -1710,7 +1730,7 @@ CommandInterpreter::HandleCommand (const char *command_line,
}
}
- if (cmd_obj == NULL)
+ if (cmd_obj == nullptr)
{
const size_t num_matches = matches.GetSize();
if (matches.GetSize() > 1) {
@@ -1823,13 +1843,13 @@ CommandInterpreter::HandleCommand (const char *command_line,
// Take care of things like setting up the history command & calling the appropriate Execute method on the
// CommandObject, with the appropriate arguments.
- if (cmd_obj != NULL)
+ if (cmd_obj != nullptr)
{
if (add_to_history)
{
Args command_args (revised_command_line.GetData());
const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
- if (repeat_command != NULL)
+ if (repeat_command != nullptr)
m_repeat_command.assign(repeat_command);
else
m_repeat_command.assign(original_command_string.c_str());
@@ -1931,7 +1951,7 @@ CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
if (num_command_matches == 1
&& cmd_obj && cmd_obj->IsMultiwordObject()
- && matches.GetStringAtIndex(0) != NULL
+ && matches.GetStringAtIndex(0) != nullptr
&& strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
{
if (parsed_line.GetArgumentCount() == 1)
@@ -1956,7 +1976,7 @@ CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
// to complete the command.
// First see if there is a matching initial command:
CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
- if (command_object == NULL)
+ if (command_object == nullptr)
{
return 0;
}
@@ -2002,7 +2022,7 @@ CommandInterpreter::HandleCompletion (const char *current_line,
else if (first_arg[0] == CommandHistory::g_repeat_char)
{
const char *history_string = m_command_history.FindString (first_arg);
- if (history_string != NULL)
+ if (history_string != nullptr)
{
matches.Clear();
matches.InsertStringAtIndex(0, history_string);
@@ -2254,7 +2274,7 @@ CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
}
}
- else if (index >= cmd_args.GetArgumentCount())
+ else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount())
{
result.AppendErrorWithFormat
("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
@@ -2364,17 +2384,21 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
// "-" and the name of the program. If this file doesn't exist, we fall
// back to just the "~/.lldbinit" file. We also obey any requests to not
// load the init files.
- const char *init_file_path = "~/.lldbinit";
+ llvm::SmallString<64> home_dir_path;
+ llvm::sys::path::home_directory(home_dir_path);
+ FileSpec profilePath(home_dir_path.c_str(), false);
+ profilePath.AppendPathComponent(".lldbinit");
+ std::string init_file_path = profilePath.GetPath();
if (m_skip_app_init_files == false)
{
- FileSpec program_file_spec (Host::GetProgramFileSpec());
+ FileSpec program_file_spec(HostInfo::GetProgramFileSpec());
const char *program_name = program_file_spec.GetFilename().AsCString();
if (program_name)
{
char program_init_file_name[PATH_MAX];
- ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name);
+ ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path.c_str(), program_name);
init_file.SetFile (program_init_file_name, true);
if (!init_file.Exists())
init_file.Clear();
@@ -2382,7 +2406,7 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
}
if (!init_file && !m_skip_lldbinit_files)
- init_file.SetFile (init_file_path, true);
+ init_file.SetFile (init_file_path.c_str(), false);
}
// If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
@@ -2392,7 +2416,7 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
{
const bool saved_batch = SetBatchCommandMode (true);
HandleCommandsFromFile (init_file,
- NULL, // Execution context
+ nullptr, // Execution context
eLazyBoolYes, // Stop on continue
eLazyBoolNo, // Stop on error
eLazyBoolNo, // Don't echo commands
@@ -2445,7 +2469,7 @@ CommandInterpreter::HandleCommands (const StringList &commands,
// If we've been given an execution context, set it at the start, but don't keep resetting it or we will
// cause series of commands that change the context, then do an operation that relies on that context to fail.
- if (override_context != NULL)
+ if (override_context != nullptr)
UpdateExecutionContext (override_context);
if (!stop_on_continue)
@@ -2475,9 +2499,9 @@ CommandInterpreter::HandleCommands (const StringList &commands,
if (!add_to_history)
m_command_source_depth++;
bool success = HandleCommand(cmd, add_to_history, tmp_result,
- NULL, /* override_context */
+ nullptr, /* override_context */
true, /* repeat_on_empty_command */
- override_context != NULL /* no_context_switching */);
+ override_context != nullptr /* no_context_switching */);
if (!add_to_history)
m_command_source_depth--;
@@ -2490,20 +2514,20 @@ CommandInterpreter::HandleCommands (const StringList &commands,
if (!success || !tmp_result.Succeeded())
{
const char *error_msg = tmp_result.GetErrorData();
- if (error_msg == NULL || error_msg[0] == '\0')
+ if (error_msg == nullptr || error_msg[0] == '\0')
error_msg = "<unknown error>.\n";
if (stop_on_error)
{
- result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' failed with %s",
- idx, cmd, error_msg);
+ result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' failed with %s",
+ (uint64_t)idx, cmd, error_msg);
result.SetStatus (eReturnStatusFailed);
m_debugger.SetAsyncExecution (old_async_execution);
return;
}
else if (print_results)
{
- result.AppendMessageWithFormat ("Command #%zu '%s' failed with %s",
- idx + 1,
+ result.AppendMessageWithFormat ("Command #%" PRIu64 " '%s' failed with %s",
+ (uint64_t)idx + 1,
cmd,
error_msg);
}
@@ -2527,10 +2551,10 @@ CommandInterpreter::HandleCommands (const StringList &commands,
// status in our real result before returning. This is an error if the continue was not the
// last command in the set of commands to be run.
if (idx != num_lines - 1)
- result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' continued the target.\n",
- idx + 1, cmd);
+ result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' continued the target.\n",
+ (uint64_t)idx + 1, cmd);
else
- result.AppendMessageWithFormat ("Command #%zu '%s' continued the target.\n", idx + 1, cmd);
+ result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' continued the target.\n", (uint64_t)idx + 1, cmd);
result.SetStatus(tmp_result.GetStatus());
m_debugger.SetAsyncExecution (old_async_execution);
@@ -2660,9 +2684,10 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
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,
- NULL, // Pass in NULL for "editline_name" so no history is saved, or written
+ nullptr, // Pass in NULL for "editline_name" so no history is saved, or written
debugger.GetPrompt(),
false, // Not multi-line
+ 0,
*this));
const bool old_async_execution = debugger.GetAsyncExecution();
@@ -2699,11 +2724,11 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
ScriptInterpreter *
CommandInterpreter::GetScriptInterpreter (bool can_create)
{
- if (m_script_interpreter_ap.get() != NULL)
+ if (m_script_interpreter_ap.get() != nullptr)
return m_script_interpreter_ap.get();
if (!can_create)
- return NULL;
+ return nullptr;
// <rdar://problem/11751427>
// we need to protect the initialization of the script interpreter
@@ -2928,7 +2953,7 @@ CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList
void
CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
{
- if (override_context != NULL)
+ if (override_context != nullptr)
{
m_exe_ctx_ref = *override_context;
}
@@ -3041,6 +3066,24 @@ CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &
}
}
+bool
+CommandInterpreter::IOHandlerInterrupt (IOHandler &io_handler)
+{
+ ExecutionContext exe_ctx (GetExecutionContext());
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process)
+ {
+ StateType state = process->GetState();
+ if (StateIsRunningState(state))
+ {
+ process->Halt();
+ return true; // Don't do any updating when we are running
+ }
+ }
+ return false;
+}
+
void
CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt,
IOHandlerDelegate &delegate,
@@ -3052,6 +3095,7 @@ CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt,
"lldb", // Name of input reader for history
prompt, // Prompt
true, // Get multiple lines
+ 0, // Don't show line numbers
delegate)); // IOHandlerDelegate
if (io_handler_sp)
@@ -3077,6 +3121,7 @@ CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt,
"lldb-python", // Name of input reader for history
prompt, // Prompt
true, // Get multiple lines
+ 0, // Don't show line numbers
delegate)); // IOHandlerDelegate
if (io_handler_sp)
@@ -3100,17 +3145,23 @@ void
CommandInterpreter::RunCommandInterpreter(bool auto_handle_events,
bool spawn_thread)
{
- const bool multiple_lines = false; // Only get one line at a time
- if (!m_command_io_handler_sp)
- 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,
- *this));
+ // 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 (auto_handle_events)
diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp
index c6995366c87a..3fdbf994fe7a 100644
--- a/source/Interpreter/CommandObject.cpp
+++ b/source/Interpreter/CommandObject.cpp
@@ -56,8 +56,9 @@ CommandObject::CommandObject
m_is_alias (false),
m_flags (flags),
m_arguments(),
- m_command_override_callback (NULL),
- m_command_override_baton (NULL)
+ m_deprecated_command_override_callback (nullptr),
+ m_command_override_callback (nullptr),
+ m_command_override_baton (nullptr)
{
if (help && help[0])
m_cmd_help_short = help;
@@ -88,7 +89,7 @@ CommandObject::GetSyntax ()
{
StreamString syntax_str;
syntax_str.Printf ("%s", GetCommandName());
- if (GetOptions() != NULL)
+ if (GetOptions() != nullptr)
syntax_str.Printf (" <cmd-options>");
if (m_arguments.size() > 0)
{
@@ -144,7 +145,7 @@ CommandObject::GetOptions ()
{
// By default commands don't have options unless this virtual function
// is overridden by base classes.
- return NULL;
+ return nullptr;
}
bool
@@ -156,7 +157,7 @@ CommandObject::ParseOptions
{
// See if the subclass has options?
Options *options = GetOptions();
- if (options != NULL)
+ if (options != nullptr)
{
Error error;
options->NotifyOptionParsingStarting();
@@ -251,7 +252,7 @@ CommandObject::CheckRequirements (CommandReturnObject &result)
return false;
}
- if ((flags & eFlagRequiresRegContext) && (m_exe_ctx.GetRegisterContext() == NULL))
+ if ((flags & eFlagRequiresRegContext) && (m_exe_ctx.GetRegisterContext() == nullptr))
{
result.AppendError (GetInvalidRegContextDescription());
return false;
@@ -268,7 +269,7 @@ CommandObject::CheckRequirements (CommandReturnObject &result)
if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process == NULL)
+ if (process == nullptr)
{
// A process that is not running is considered paused.
if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched))
@@ -335,7 +336,7 @@ class CommandDictCommandPartialMatch
bool operator() (const std::pair<std::string, lldb::CommandObjectSP> map_element) const
{
// A NULL or empty string matches everything.
- if (m_match_str == NULL || *m_match_str == '\0')
+ if (m_match_str == nullptr || *m_match_str == '\0')
return true;
return map_element.first.find (m_match_str, 0) == 0;
@@ -392,7 +393,7 @@ CommandObject::HandleCompletion
CommandReturnObject result;
OptionElementVector opt_element_vector;
- if (cur_options != NULL)
+ if (cur_options != nullptr)
{
// Re-insert the dummy command name string which will have been
// stripped off:
@@ -453,7 +454,7 @@ CommandObject::HelpTextContainsWord (const char *search_word)
found_word = true;
if (!found_word
- && GetOptions() != NULL)
+ && GetOptions() != nullptr)
{
StreamString usage_help;
GetOptions()->GenerateOptionUsage (usage_help, this);
@@ -477,10 +478,10 @@ CommandObject::GetNumArgumentEntries ()
CommandObject::CommandArgumentEntry *
CommandObject::GetArgumentEntryAtIndex (int idx)
{
- if (idx < m_arguments.size())
+ if (static_cast<size_t>(idx) < m_arguments.size())
return &(m_arguments[idx]);
- return NULL;
+ return nullptr;
}
CommandObject::ArgumentTableEntry *
@@ -492,7 +493,7 @@ CommandObject::FindArgumentDataByType (CommandArgumentType arg_type)
if (table[i].arg_type == arg_type)
return (ArgumentTableEntry *) &(table[i]);
- return NULL;
+ return nullptr;
}
void
@@ -771,7 +772,7 @@ static const char *
FormatHelpTextCallback ()
{
- static char* help_text_ptr = NULL;
+ static char* help_text_ptr = nullptr;
if (help_text_ptr)
return help_text_ptr;
@@ -804,7 +805,7 @@ FormatHelpTextCallback ()
static const char *
LanguageTypeHelpTextCallback ()
{
- static char* help_text_ptr = NULL;
+ static char* help_text_ptr = nullptr;
if (help_text_ptr)
return help_text_ptr;
@@ -900,7 +901,7 @@ void
CommandObject::GenerateHelpText (Stream &output_strm)
{
CommandInterpreter& interpreter = GetCommandInterpreter();
- if (GetOptions() != NULL)
+ if (GetOptions() != nullptr)
{
if (WantsRawCommandString())
{
@@ -913,7 +914,7 @@ CommandObject::GenerateHelpText (Stream &output_strm)
output_strm.Printf ("\nSyntax: %s\n", GetSyntax());
GetOptions()->GenerateOptionUsage (output_strm, this);
const char *long_help = GetHelpLong();
- if ((long_help != NULL)
+ if ((long_help != nullptr)
&& (strlen (long_help) > 0))
output_strm.Printf ("\n%s", long_help);
if (WantsRawCommandString() && !WantsCompletion())
@@ -950,7 +951,7 @@ CommandObject::GenerateHelpText (Stream &output_strm)
else
{
const char *long_help = GetHelpLong();
- if ((long_help != NULL)
+ if ((long_help != nullptr)
&& (strlen (long_help) > 0))
output_strm.Printf ("%s", long_help);
else if (WantsRawCommandString())
@@ -990,7 +991,7 @@ CommandObject::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_typ
{
if (arg_type >=0 && arg_type < eArgTypeLastArg)
return g_arguments_data[arg_type].arg_name;
- return NULL;
+ return nullptr;
}
@@ -999,20 +1000,19 @@ CommandObject::GetArgumentDescriptionAsCString (const lldb::CommandArgumentType
{
if (arg_type >=0 && arg_type < eArgTypeLastArg)
return g_arguments_data[arg_type].help_text;
- return NULL;
+ return nullptr;
}
bool
CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &result)
{
- CommandOverrideCallback command_callback = GetOverrideCallback();
bool handled = false;
Args cmd_args (args_string);
- if (command_callback)
+ if (HasOverrideCallback())
{
Args full_args (GetCommandName ());
full_args.AppendArguments(cmd_args);
- handled = command_callback (GetOverrideCallbackBaton(), full_args.GetConstArgumentVector());
+ handled = InvokeOverrideCallback (full_args.GetConstArgumentVector(), result);
}
if (!handled)
{
@@ -1040,16 +1040,15 @@ CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &resu
bool
CommandObjectRaw::Execute (const char *args_string, CommandReturnObject &result)
{
- CommandOverrideCallback command_callback = GetOverrideCallback();
bool handled = false;
- if (command_callback)
+ if (HasOverrideCallback())
{
std::string full_command (GetCommandName ());
full_command += ' ';
full_command += args_string;
- const char *argv[2] = { NULL, NULL };
+ const char *argv[2] = { nullptr, nullptr };
argv[0] = full_command.c_str();
- handled = command_callback (GetOverrideCallbackBaton(), argv);
+ handled = InvokeOverrideCallback (argv, result);
}
if (!handled)
{
@@ -1068,7 +1067,7 @@ const char *arch_helper()
if (g_archs_help.Empty())
{
StringList archs;
- ArchSpec::AutoComplete(NULL, archs);
+ ArchSpec::AutoComplete(nullptr, archs);
g_archs_help.Printf("These are the supported architecture names:\n");
archs.Join("\n", g_archs_help);
}
@@ -1078,86 +1077,86 @@ const char *arch_helper()
CommandObject::ArgumentTableEntry
CommandObject::g_arguments_data[] =
{
- { eArgTypeAddress, "address", CommandCompletions::eNoCompletion, { NULL, false }, "A valid address in the target program's execution space." },
- { eArgTypeAddressOrExpression, "address-expression", CommandCompletions::eNoCompletion, { NULL, false }, "An expression that resolves to an address." },
- { eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of an abbreviation (alias) for a debugger command." },
- { eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, { NULL, false }, "Command options to be used as part of an alias (abbreviation) definition. (See 'help commands alias' for more information.)" },
+ { eArgTypeAddress, "address", CommandCompletions::eNoCompletion, { nullptr, false }, "A valid address in the target program's execution space." },
+ { eArgTypeAddressOrExpression, "address-expression", CommandCompletions::eNoCompletion, { nullptr, false }, "An expression that resolves to an address." },
+ { eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of an abbreviation (alias) for a debugger command." },
+ { eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, { nullptr, false }, "Command options to be used as part of an alias (abbreviation) definition. (See 'help commands alias' for more information.)" },
{ eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, { arch_helper, true }, "The architecture name, e.g. i386 or x86_64." },
- { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { NULL, false }, "A Boolean value: 'true' or 'false'" },
- { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, NULL },
- { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, NULL },
- { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { NULL, false }, "Number of bytes to use." },
- { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { NULL, false }, "Then name of a class from the debug information in the program." },
- { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { NULL, false }, "A debugger command (may be multiple words), without any options or arguments." },
- { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." },
- { eArgTypeDirectoryName, "directory", CommandCompletions::eDiskDirectoryCompletion, { NULL, false }, "A directory name." },
- { eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eNoCompletion, { NULL, false }, "A disassembly flavor recognized by your disassembly plugin. Currently the only valid options are \"att\" and \"intel\" for Intel targets" },
- { eArgTypeDescriptionVerbosity, "description-verbosity", CommandCompletions::eNoCompletion, { NULL, false }, "How verbose the output of 'po' should be." },
- { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
- { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
- { eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, NULL },
- { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { NULL, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" },
- { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { NULL, false }, "The name of a file (can include path)." },
- { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, NULL },
- { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into a thread's list of frames." },
- { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
- { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a function." },
- { eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a function or symbol." },
- { eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, { GDBFormatHelpTextCallback, true }, NULL },
- { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { NULL, false }, "An index into a list." },
- { eArgTypeLanguage, "language", CommandCompletions::eNoCompletion, { LanguageTypeHelpTextCallback, true }, NULL },
- { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { NULL, false }, "Line number in a source file." },
- { eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." },
- { eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." },
- { eArgTypeMethod, "method", CommandCompletions::eNoCompletion, { NULL, false }, "A C++ method name." },
- { eArgTypeName, "name", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
- { eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
- { eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, { NULL, false }, "The number of lines to use." },
- { eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, { NULL, false }, "The number of items per line to display." },
- { eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
- { eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
- { eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, { NULL, false }, "A command that is entered as a single line of text." },
- { eArgTypePath, "path", CommandCompletions::eDiskFileCompletion, { NULL, false }, "Path." },
- { eArgTypePermissionsNumber, "perms-numeric", CommandCompletions::eNoCompletion, { NULL, false }, "Permissions given as an octal number (e.g. 755)." },
- { eArgTypePermissionsString, "perms=string", CommandCompletions::eNoCompletion, { NULL, false }, "Permissions given as a string value (e.g. rw-r-xr--)." },
- { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { NULL, false }, "The process ID number." },
- { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
- { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the process." },
- { eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python class." },
- { eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python function." },
- { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { NULL, false }, "Source code written in Python." },
- { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the thread queue." },
- { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { RegisterNameHelpTextCallback, true }, NULL },
- { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { NULL, false }, "A regular expression." },
- { eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, { NULL, false }, "Arguments to be passed to the target program when it starts executing." },
- { eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
- { eArgTypeScriptedCommandSynchronicity, "script-cmd-synchronicity", CommandCompletions::eNoCompletion, { NULL, false }, "The synchronicity to use to run scripted commands with regard to LLDB event system." },
- { eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, { NULL, false }, "The scripting language to be used for script-based commands. Currently only Python is valid." },
- { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, { NULL, false }, "The word for which you wish to search for information about." },
- { eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, { NULL, false }, "An Objective-C selector name." },
- { eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, { NULL, false }, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." },
- { eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, { NULL, false }, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." },
- { eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" },
- { eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a settable internal debugger variable. Type 'settings list' to see a complete list of such variables." },
- { eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a shared library." },
- { eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, { NULL, false }, "The name of a source file.." },
- { eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, { NULL, false }, "Specify a sort order when dumping lists." },
- { eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
- { eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, { SummaryStringHelpTextCallback, true }, NULL },
- { eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, { NULL, false }, "Any symbol name (function name, variable, argument, etc.)" },
- { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { NULL, false }, "Thread ID number." },
- { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into the process' list of threads." },
- { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { NULL, false }, "The thread's name." },
- { eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." },
- { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { NULL, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." },
- { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a variable in your program." },
- { eArgTypeValue, "value", CommandCompletions::eNoCompletion, { NULL, false }, "A value could be anything, depending on where and how it is used." },
- { eArgTypeWidth, "width", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
- { eArgTypeNone, "none", CommandCompletions::eNoCompletion, { NULL, false }, "No help available for this." },
- { eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, { NULL, false }, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." },
- { eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, { NULL, false }, "Watchpoint IDs are positive integers." },
- { eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, { NULL, false }, "For example, '1-3' or '1 to 3'." },
- { eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { NULL, false }, "Specify the type for a watchpoint." }
+ { 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 },
+ { 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." },
+ { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { nullptr, false }, "An unsigned integer." },
+ { eArgTypeDirectoryName, "directory", CommandCompletions::eDiskDirectoryCompletion, { nullptr, false }, "A directory name." },
+ { eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eNoCompletion, { nullptr, false }, "A disassembly flavor recognized by your disassembly plugin. Currently the only valid options are \"att\" and \"intel\" for Intel targets" },
+ { eArgTypeDescriptionVerbosity, "description-verbosity", CommandCompletions::eNoCompletion, { nullptr, false }, "How verbose the output of 'po' should be." },
+ { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
+ { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
+ { eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, nullptr },
+ { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { nullptr, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" },
+ { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { nullptr, false }, "The name of a file (can include path)." },
+ { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, nullptr },
+ { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, { nullptr, false }, "Index into a thread's list of frames." },
+ { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
+ { 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 },
+ { 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." },
+ { eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." },
+ { eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." },
+ { eArgTypeMethod, "method", CommandCompletions::eNoCompletion, { nullptr, false }, "A C++ method name." },
+ { eArgTypeName, "name", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
+ { eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
+ { eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, { nullptr, false }, "The number of lines to use." },
+ { eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, { nullptr, false }, "The number of items per line to display." },
+ { eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
+ { eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
+ { eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, { nullptr, false }, "A command that is entered as a single line of text." },
+ { eArgTypePath, "path", CommandCompletions::eDiskFileCompletion, { nullptr, false }, "Path." },
+ { eArgTypePermissionsNumber, "perms-numeric", CommandCompletions::eNoCompletion, { nullptr, false }, "Permissions given as an octal number (e.g. 755)." },
+ { eArgTypePermissionsString, "perms=string", CommandCompletions::eNoCompletion, { nullptr, false }, "Permissions given as a string value (e.g. rw-r-xr--)." },
+ { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { nullptr, false }, "The process ID number." },
+ { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
+ { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of the process." },
+ { eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a Python class." },
+ { eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a Python function." },
+ { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { nullptr, false }, "Source code written in Python." },
+ { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of the thread queue." },
+ { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { RegisterNameHelpTextCallback, true }, nullptr },
+ { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { nullptr, false }, "A regular expression." },
+ { eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, { nullptr, false }, "Arguments to be passed to the target program when it starts executing." },
+ { eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
+ { eArgTypeScriptedCommandSynchronicity, "script-cmd-synchronicity", CommandCompletions::eNoCompletion, { nullptr, false }, "The synchronicity to use to run scripted commands with regard to LLDB event system." },
+ { eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, { nullptr, false }, "The scripting language to be used for script-based commands. Currently only Python is valid." },
+ { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, { nullptr, false }, "The word for which you wish to search for information about." },
+ { eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, { nullptr, false }, "An Objective-C selector name." },
+ { eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, { nullptr, false }, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." },
+ { eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, { nullptr, false }, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." },
+ { eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" },
+ { eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a settable internal debugger variable. Type 'settings list' to see a complete list of such variables." },
+ { eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a shared library." },
+ { eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, { nullptr, false }, "The name of a source file.." },
+ { eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify a sort order when dumping lists." },
+ { eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
+ { eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, { SummaryStringHelpTextCallback, true }, nullptr },
+ { eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, { nullptr, false }, "Any symbol name (function name, variable, argument, etc.)" },
+ { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Thread ID number." },
+ { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { nullptr, false }, "Index into the process' list of threads." },
+ { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The thread's name." },
+ { eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, { nullptr, false }, "An unsigned integer." },
+ { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { nullptr, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." },
+ { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a variable in your program." },
+ { eArgTypeValue, "value", CommandCompletions::eNoCompletion, { nullptr, false }, "A value could be anything, depending on where and how it is used." },
+ { eArgTypeWidth, "width", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
+ { eArgTypeNone, "none", CommandCompletions::eNoCompletion, { nullptr, false }, "No help available for this." },
+ { eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, { nullptr, false }, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." },
+ { eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Watchpoint IDs are positive integers." },
+ { eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, { nullptr, false }, "For example, '1-3' or '1 to 3'." },
+ { eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify the type for a watchpoint." }
};
const CommandObject::ArgumentTableEntry*
diff --git a/source/Interpreter/CommandObjectRegexCommand.cpp b/source/Interpreter/CommandObjectRegexCommand.cpp
index 59cf1f05fb65..d27320dd1f3d 100644
--- a/source/Interpreter/CommandObjectRegexCommand.cpp
+++ b/source/Interpreter/CommandObjectRegexCommand.cpp
@@ -86,11 +86,11 @@ CommandObjectRegexCommand::DoExecute
result.GetOutputStream().Printf("%s\n", new_command.c_str());
// Pass in true for "no context switching". The command that called us should have set up the context
// appropriately, we shouldn't have to redo that.
- return m_interpreter.HandleCommand(new_command.c_str(), eLazyBoolCalculate, result, NULL, true, true);
+ return m_interpreter.HandleCommand(new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true);
}
}
result.SetStatus(eReturnStatusFailed);
- if (GetSyntax() != NULL)
+ if (GetSyntax() != nullptr)
result.AppendError (GetSyntax());
else
result.AppendErrorWithFormat ("Command contents '%s' failed to match any regular expression in the '%s' regex command.\n",
@@ -136,7 +136,7 @@ CommandObjectRegexCommand::HandleCompletion (Args &input,
completion_str.c_str(),
match_start_point,
max_return_elements,
- NULL,
+ nullptr,
word_complete,
matches);
return matches.GetSize();
diff --git a/source/Interpreter/CommandObjectScript.cpp b/source/Interpreter/CommandObjectScript.cpp
index aff507d98580..9c67e4253301 100644
--- a/source/Interpreter/CommandObjectScript.cpp
+++ b/source/Interpreter/CommandObjectScript.cpp
@@ -66,7 +66,7 @@ CommandObjectScript::DoExecute
ScriptInterpreter *script_interpreter = m_interpreter.GetScriptInterpreter ();
- if (script_interpreter == NULL)
+ if (script_interpreter == nullptr)
{
result.AppendError("no script interpreter");
result.SetStatus (eReturnStatusFailed);
@@ -75,7 +75,7 @@ CommandObjectScript::DoExecute
DataVisualization::ForceUpdate(); // script might change Python code we use for formatting.. make sure we keep up to date with it
- if (command == NULL || command[0] == '\0')
+ if (command == nullptr || command[0] == '\0')
{
script_interpreter->ExecuteInterpreterLoop ();
result.SetStatus (eReturnStatusSuccessFinishNoResult);
diff --git a/source/Interpreter/CommandOptionValidators.cpp b/source/Interpreter/CommandOptionValidators.cpp
new file mode 100644
index 000000000000..7d66de53c0b4
--- /dev/null
+++ b/source/Interpreter/CommandOptionValidators.cpp
@@ -0,0 +1,39 @@
+//===-- CommandOptionValidators.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/CommandOptionValidators.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/Platform.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool PosixPlatformCommandOptionValidator::IsValid(Platform &platform, const ExecutionContext &target) const
+{
+ llvm::Triple::OSType os = platform.GetSystemArchitecture().GetTriple().getOS();
+ switch (os)
+ {
+ // Are there any other platforms that are not POSIX-compatible?
+ case llvm::Triple::Win32:
+ return false;
+ default:
+ return true;
+ }
+}
+
+const char* PosixPlatformCommandOptionValidator::ShortConditionString() const
+{
+ return "POSIX";
+}
+
+const char* PosixPlatformCommandOptionValidator::LongConditionString() const
+{
+ return "Option only valid for POSIX-compliant hosts.";
+}
diff --git a/source/Interpreter/CommandReturnObject.cpp b/source/Interpreter/CommandReturnObject.cpp
index 9c63753a23ff..1b5418735069 100644
--- a/source/Interpreter/CommandReturnObject.cpp
+++ b/source/Interpreter/CommandReturnObject.cpp
@@ -46,7 +46,8 @@ CommandReturnObject::CommandReturnObject () :
m_out_stream (),
m_err_stream (),
m_status (eReturnStatusStarted),
- m_did_change_process_state (false)
+ m_did_change_process_state (false),
+ m_interactive (true)
{
}
@@ -141,7 +142,7 @@ void
CommandReturnObject::SetError (const Error &error, const char *fallback_error_cstr)
{
const char *error_cstr = error.AsCString();
- if (error_cstr == NULL)
+ if (error_cstr == nullptr)
error_cstr = fallback_error_cstr;
SetError(error_cstr);
}
@@ -203,6 +204,7 @@ CommandReturnObject::Clear()
static_cast<StreamString *>(stream_sp.get())->Clear();
m_status = eReturnStatusStarted;
m_did_change_process_state = false;
+ m_interactive = true;
}
bool
@@ -217,3 +219,17 @@ CommandReturnObject::SetDidChangeProcessState (bool b)
m_did_change_process_state = b;
}
+
+bool
+CommandReturnObject::GetInteractive () const
+{
+ return m_interactive;
+}
+
+void
+CommandReturnObject::SetInteractive (bool b)
+{
+ m_interactive = b;
+}
+
+
diff --git a/source/Interpreter/OptionGroupArchitecture.cpp b/source/Interpreter/OptionGroupArchitecture.cpp
index d8f35675fbab..3a454093ab29 100644
--- a/source/Interpreter/OptionGroupArchitecture.cpp
+++ b/source/Interpreter/OptionGroupArchitecture.cpp
@@ -30,7 +30,7 @@ OptionGroupArchitecture::~OptionGroupArchitecture ()
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1 , false, "arch" , 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeArchitecture , "Specify the architecture for the target."},
+ { LLDB_OPT_SET_1 , false, "arch" , 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture , "Specify the architecture for the target."},
};
uint32_t
diff --git a/source/Interpreter/OptionGroupBoolean.cpp b/source/Interpreter/OptionGroupBoolean.cpp
index feb135315e1b..0c502cc364b4 100644
--- a/source/Interpreter/OptionGroupBoolean.cpp
+++ b/source/Interpreter/OptionGroupBoolean.cpp
@@ -30,8 +30,9 @@ OptionGroupBoolean::OptionGroupBoolean (uint32_t usage_mask,
m_option_definition.required = required;
m_option_definition.long_option = long_option;
m_option_definition.short_option = short_option;
+ m_option_definition.validator = nullptr;
m_option_definition.option_has_arg = no_argument_toggle_default ? OptionParser::eNoArgument : OptionParser::eRequiredArgument;
- m_option_definition.enum_values = NULL;
+ m_option_definition.enum_values = nullptr;
m_option_definition.completion_type = 0;
m_option_definition.argument_type = eArgTypeBoolean;
m_option_definition.usage_text = usage_text;
diff --git a/source/Interpreter/OptionGroupFile.cpp b/source/Interpreter/OptionGroupFile.cpp
index 48469a80417e..9bfe8ddf0282 100644
--- a/source/Interpreter/OptionGroupFile.cpp
+++ b/source/Interpreter/OptionGroupFile.cpp
@@ -30,8 +30,9 @@ OptionGroupFile::OptionGroupFile (uint32_t usage_mask,
m_option_definition.required = required;
m_option_definition.long_option = long_option;
m_option_definition.short_option = short_option;
+ m_option_definition.validator = nullptr;
m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
- m_option_definition.enum_values = NULL;
+ m_option_definition.enum_values = nullptr;
m_option_definition.completion_type = completion_type;
m_option_definition.argument_type = argument_type;
m_option_definition.usage_text = usage_text;
@@ -70,8 +71,9 @@ OptionGroupFileList::OptionGroupFileList (uint32_t usage_mask,
m_option_definition.required = required;
m_option_definition.long_option = long_option;
m_option_definition.short_option = short_option;
+ m_option_definition.validator = nullptr;
m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
- m_option_definition.enum_values = NULL;
+ m_option_definition.enum_values = nullptr;
m_option_definition.completion_type = completion_type;
m_option_definition.argument_type = argument_type;
m_option_definition.usage_text = usage_text;
diff --git a/source/Interpreter/OptionGroupFormat.cpp b/source/Interpreter/OptionGroupFormat.cpp
index 5cae3788f3bf..601a78458730 100644
--- a/source/Interpreter/OptionGroupFormat.cpp
+++ b/source/Interpreter/OptionGroupFormat.cpp
@@ -42,10 +42,10 @@ OptionGroupFormat::~OptionGroupFormat ()
static OptionDefinition
g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "format" ,'f', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFormat , "Specify a format to be used for display."},
-{ LLDB_OPT_SET_2, false, "gdb-format",'G', OptionParser::eRequiredArgument, NULL, 0, eArgTypeGDBFormat, "Specify a format using a GDB format specifier string."},
-{ LLDB_OPT_SET_3, false, "size" ,'s', OptionParser::eRequiredArgument, NULL, 0, eArgTypeByteSize , "The size in bytes to use when displaying with the selected format."},
-{ LLDB_OPT_SET_4, false, "count" ,'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount , "The number of total items to display."},
+{ LLDB_OPT_SET_1, false, "format" ,'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFormat , "Specify a format to be used for display."},
+{ LLDB_OPT_SET_2, false, "gdb-format",'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeGDBFormat, "Specify a format using a GDB format specifier string."},
+{ LLDB_OPT_SET_3, false, "size" ,'s', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeByteSize , "The size in bytes to use when displaying with the selected format."},
+{ LLDB_OPT_SET_4, false, "count" ,'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount , "The number of total items to display."},
};
uint32_t
@@ -109,7 +109,7 @@ OptionGroupFormat::SetOptionValue (CommandInterpreter &interpreter,
case 'G':
{
- char *end = NULL;
+ char *end = nullptr;
const char *gdb_format_cstr = option_arg;
uint64_t count = 0;
if (::isdigit (gdb_format_cstr[0]))
diff --git a/source/Interpreter/OptionGroupOutputFile.cpp b/source/Interpreter/OptionGroupOutputFile.cpp
index 3bb8ab3b29cb..ec9e166d2f05 100644
--- a/source/Interpreter/OptionGroupOutputFile.cpp
+++ b/source/Interpreter/OptionGroupOutputFile.cpp
@@ -28,11 +28,15 @@ OptionGroupOutputFile::~OptionGroupOutputFile ()
{
}
+static const uint32_t SHORT_OPTION_APND = 0x61706e64; // 'apnd'
+
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1 , false, "outfile", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename , "Specify a path for capturing command output."},
- { LLDB_OPT_SET_1 , false, "append-outfile" , 'apnd', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Append to the the file specified with '--outfile <path>'."},
+ { LLDB_OPT_SET_1 , false, "outfile", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename , "Specify a path for capturing command output."},
+ { LLDB_OPT_SET_1 , false, "append-outfile" , SHORT_OPTION_APND,
+ OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone ,
+ "Append to the the file specified with '--outfile <path>'."},
};
uint32_t
@@ -61,7 +65,7 @@ OptionGroupOutputFile::SetOptionValue (CommandInterpreter &interpreter,
error = m_file.SetValueFromCString (option_arg);
break;
- case 'apnd':
+ case SHORT_OPTION_APND:
m_append.SetCurrentValue(true);
break;
diff --git a/source/Interpreter/OptionGroupPlatform.cpp b/source/Interpreter/OptionGroupPlatform.cpp
index 83e28bdd02c1..9ffd5f072d90 100644
--- a/source/Interpreter/OptionGroupPlatform.cpp
+++ b/source/Interpreter/OptionGroupPlatform.cpp
@@ -85,10 +85,10 @@ OptionGroupPlatform::OptionParsingStarting (CommandInterpreter &interpreter)
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "platform", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlatform, "Specify name of the platform to use for this target, creating the platform if necessary."},
- { LLDB_OPT_SET_ALL, false, "version" , 'v', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone, "Specify the initial SDK version to use prior to connecting." },
- { LLDB_OPT_SET_ALL, false, "build" , 'b', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone, "Specify the initial SDK build number." },
- { LLDB_OPT_SET_ALL, false, "sysroot" , 'S', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Specify the SDK root directory that contains a root of all remote system files." }
+ { LLDB_OPT_SET_ALL, false, "platform", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlatform, "Specify name of the platform to use for this target, creating the platform if necessary."},
+ { LLDB_OPT_SET_ALL, false, "version" , 'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "Specify the initial SDK version to use prior to connecting." },
+ { LLDB_OPT_SET_ALL, false, "build" , 'b', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "Specify the initial SDK build number." },
+ { LLDB_OPT_SET_ALL, false, "sysroot" , 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Specify the SDK root directory that contains a root of all remote system files." }
};
const OptionDefinition*
diff --git a/source/Interpreter/OptionGroupString.cpp b/source/Interpreter/OptionGroupString.cpp
index 37a70d0bb242..9bc1c94d3a5a 100644
--- a/source/Interpreter/OptionGroupString.cpp
+++ b/source/Interpreter/OptionGroupString.cpp
@@ -31,8 +31,9 @@ OptionGroupString::OptionGroupString (uint32_t usage_mask,
m_option_definition.required = required;
m_option_definition.long_option = long_option;
m_option_definition.short_option = short_option;
+ m_option_definition.validator = nullptr;
m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
- m_option_definition.enum_values = NULL;
+ m_option_definition.enum_values = nullptr;
m_option_definition.completion_type = completion_type;
m_option_definition.argument_type = argument_type;
m_option_definition.usage_text = usage_text;
diff --git a/source/Interpreter/OptionGroupUInt64.cpp b/source/Interpreter/OptionGroupUInt64.cpp
index b66c84579232..440c2a740c26 100644
--- a/source/Interpreter/OptionGroupUInt64.cpp
+++ b/source/Interpreter/OptionGroupUInt64.cpp
@@ -31,8 +31,9 @@ OptionGroupUInt64::OptionGroupUInt64 (uint32_t usage_mask,
m_option_definition.required = required;
m_option_definition.long_option = long_option;
m_option_definition.short_option = short_option;
+ m_option_definition.validator = nullptr;
m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
- m_option_definition.enum_values = NULL;
+ m_option_definition.enum_values = nullptr;
m_option_definition.completion_type = completion_type;
m_option_definition.argument_type = argument_type;
m_option_definition.usage_text = usage_text;
diff --git a/source/Interpreter/OptionGroupUUID.cpp b/source/Interpreter/OptionGroupUUID.cpp
index fb3ebcf7745c..43f7386c9ca6 100644
--- a/source/Interpreter/OptionGroupUUID.cpp
+++ b/source/Interpreter/OptionGroupUUID.cpp
@@ -30,7 +30,7 @@ OptionGroupUUID::~OptionGroupUUID ()
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1 , false, "uuid", 'u', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone, "A module UUID value."},
+ { LLDB_OPT_SET_1 , false, "uuid", 'u', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A module UUID value."},
};
uint32_t
diff --git a/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/source/Interpreter/OptionGroupValueObjectDisplay.cpp
index c79f49dc1d94..125e5fb0a5d6 100644
--- a/source/Interpreter/OptionGroupValueObjectDisplay.cpp
+++ b/source/Interpreter/OptionGroupValueObjectDisplay.cpp
@@ -34,18 +34,18 @@ OptionGroupValueObjectDisplay::~OptionGroupValueObjectDisplay ()
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "dynamic-type", 'd', OptionParser::eRequiredArgument, g_dynamic_value_types, 0, eArgTypeNone, "Show the object as its full dynamic type, not its static type, if available."},
- { LLDB_OPT_SET_1, false, "synthetic-type", 'S', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Show the object obeying its synthetic provider, if available."},
- { LLDB_OPT_SET_1, false, "depth", 'D', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "Set the max recurse depth when dumping aggregate types (default is infinity)."},
- { LLDB_OPT_SET_1, false, "flat", 'F', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Display results in a flat format that uses expression paths for each variable or member."},
- { LLDB_OPT_SET_1, false, "location", 'L', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Show variable location information."},
- { LLDB_OPT_SET_1, false, "object-description", 'O', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Print as an Objective-C object."},
- { LLDB_OPT_SET_1, false, "ptr-depth", 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "The number of pointers to be traversed when dumping values (default is zero)."},
- { LLDB_OPT_SET_1, false, "show-types", 'T', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Show variable types when dumping values."},
- { LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', OptionParser::eOptionalArgument, NULL, 0, eArgTypeCount, "Set the depth at which omitting summary information stops (default is 1)."},
- { LLDB_OPT_SET_1, false, "raw-output", 'R', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use formatting options."},
- { LLDB_OPT_SET_1, false, "show-all-children", 'A', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Ignore the upper bound on the number of children to show."},
- { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_1, false, "dynamic-type", 'd', OptionParser::eRequiredArgument, nullptr, g_dynamic_value_types, 0, eArgTypeNone, "Show the object as its full dynamic type, not its static type, if available."},
+ { LLDB_OPT_SET_1, false, "synthetic-type", 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Show the object obeying its synthetic provider, if available."},
+ { LLDB_OPT_SET_1, false, "depth", 'D', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the max recurse depth when dumping aggregate types (default is infinity)."},
+ { LLDB_OPT_SET_1, false, "flat", 'F', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display results in a flat format that uses expression paths for each variable or member."},
+ { LLDB_OPT_SET_1, false, "location", 'L', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show variable location information."},
+ { LLDB_OPT_SET_1, false, "object-description", 'O', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print as an Objective-C object."},
+ { LLDB_OPT_SET_1, false, "ptr-depth", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "The number of pointers to be traversed when dumping values (default is zero)."},
+ { LLDB_OPT_SET_1, false, "show-types", 'T', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show variable types when dumping values."},
+ { 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."},
+ { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
};
uint32_t
@@ -139,7 +139,7 @@ OptionGroupValueObjectDisplay::OptionParsingStarting (CommandInterpreter &interp
ignore_cap = false;
Target *target = interpreter.GetExecutionContext().GetTargetPtr();
- if (target != NULL)
+ if (target != nullptr)
use_dynamic = target->GetPreferDynamicValue();
else
{
diff --git a/source/Interpreter/OptionGroupVariable.cpp b/source/Interpreter/OptionGroupVariable.cpp
index 31c2547e2c37..05cf3f73bfed 100644
--- a/source/Interpreter/OptionGroupVariable.cpp
+++ b/source/Interpreter/OptionGroupVariable.cpp
@@ -28,14 +28,14 @@ using namespace lldb_private;
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-args", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Omit function arguments."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-locals", 'l', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Omit local variables."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-globals", 'g', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Show the current frame source file global and static variables."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-declaration",'c', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Show variable declaration information (source file and line where the variable was declared)."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "regex", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeRegularExpression, "The <variable-name> argument for name lookups are regular expressions."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "scope", 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."},
- { LLDB_OPT_SET_1, false, "summary", 'y', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Specify the summary that the variable output should use."},
- { LLDB_OPT_SET_2, false, "summary-string", 'z', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Specify a summary string to use to format the variable output."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-args", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Omit function arguments."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-locals", 'l', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Omit local variables."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-globals", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show the current frame source file global and static variables."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-declaration",'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show variable declaration information (source file and line where the variable was declared)."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "regex", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "The <variable-name> argument for name lookups are regular expressions."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "scope", 's', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."},
+ { LLDB_OPT_SET_1, false, "summary", 'y', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Specify the summary that the variable output should use."},
+ { LLDB_OPT_SET_2, false, "summary-string", 'z', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Specify a summary string to use to format the variable output."},
};
static Error
diff --git a/source/Interpreter/OptionGroupWatchpoint.cpp b/source/Interpreter/OptionGroupWatchpoint.cpp
index 09dc8ed88d2f..f4d8df1e6ba7 100644
--- a/source/Interpreter/OptionGroupWatchpoint.cpp
+++ b/source/Interpreter/OptionGroupWatchpoint.cpp
@@ -25,7 +25,7 @@ static OptionEnumValueElement g_watch_type[] =
{ OptionGroupWatchpoint::eWatchRead, "read", "Watch for read"},
{ OptionGroupWatchpoint::eWatchWrite, "write", "Watch for write"},
{ OptionGroupWatchpoint::eWatchReadWrite, "read_write", "Watch for read/write"},
- { 0, NULL, NULL }
+ { 0, nullptr, nullptr }
};
static OptionEnumValueElement g_watch_size[] =
@@ -34,14 +34,14 @@ static OptionEnumValueElement g_watch_size[] =
{ 2, "2", "Watch for byte size of 2"},
{ 4, "4", "Watch for byte size of 4"},
{ 8, "8", "Watch for byte size of 8"},
- { 0, NULL, NULL }
+ { 0, nullptr, nullptr }
};
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "watch", 'w', OptionParser::eRequiredArgument, g_watch_type, 0, eArgTypeWatchType, "Specify the type of watching to perform."},
- { LLDB_OPT_SET_1, false, "xsize", 'x', OptionParser::eRequiredArgument, g_watch_size, 0, eArgTypeByteSize, "Number of bytes to use to watch a region."}
+ { LLDB_OPT_SET_1, false, "watch", 'w', OptionParser::eRequiredArgument, nullptr, g_watch_type, 0, eArgTypeWatchType, "Specify the type of watching to perform."},
+ { LLDB_OPT_SET_1, false, "xsize", 'x', OptionParser::eRequiredArgument, nullptr, g_watch_size, 0, eArgTypeByteSize, "Number of bytes to use to watch a region."}
};
diff --git a/source/Interpreter/OptionValue.cpp b/source/Interpreter/OptionValue.cpp
index 1f6b03ddac1a..bc1e1c4c4779 100644
--- a/source/Interpreter/OptionValue.cpp
+++ b/source/Interpreter/OptionValue.cpp
@@ -60,7 +60,7 @@ OptionValue::GetAsBoolean ()
{
if (GetType () == OptionValue::eTypeBoolean)
return static_cast<OptionValueBoolean *>(this);
- return NULL;
+ return nullptr;
}
const OptionValueBoolean *
@@ -68,7 +68,7 @@ OptionValue::GetAsBoolean () const
{
if (GetType () == OptionValue::eTypeBoolean)
return static_cast<const OptionValueBoolean *>(this);
- return NULL;
+ return nullptr;
}
@@ -77,7 +77,7 @@ OptionValue::GetAsFileSpec ()
{
if (GetType () == OptionValue::eTypeFileSpec)
return static_cast<OptionValueFileSpec *>(this);
- return NULL;
+ return nullptr;
}
@@ -86,7 +86,7 @@ OptionValue::GetAsFileSpec () const
{
if (GetType () == OptionValue::eTypeFileSpec)
return static_cast<const OptionValueFileSpec *>(this);
- return NULL;
+ return nullptr;
}
@@ -95,7 +95,7 @@ OptionValue::GetAsFileSpecList ()
{
if (GetType () == OptionValue::eTypeFileSpecList)
return static_cast<OptionValueFileSpecList *>(this);
- return NULL;
+ return nullptr;
}
@@ -104,7 +104,7 @@ OptionValue::GetAsFileSpecList () const
{
if (GetType () == OptionValue::eTypeFileSpecList)
return static_cast<const OptionValueFileSpecList *>(this);
- return NULL;
+ return nullptr;
}
@@ -113,7 +113,7 @@ OptionValue::GetAsArch ()
{
if (GetType () == OptionValue::eTypeArch)
return static_cast<OptionValueArch *>(this);
- return NULL;
+ return nullptr;
}
@@ -122,7 +122,7 @@ OptionValue::GetAsArch () const
{
if (GetType () == OptionValue::eTypeArch)
return static_cast<const OptionValueArch *>(this);
- return NULL;
+ return nullptr;
}
OptionValueArray *
@@ -130,7 +130,7 @@ OptionValue::GetAsArray ()
{
if (GetType () == OptionValue::eTypeArray)
return static_cast<OptionValueArray *>(this);
- return NULL;
+ return nullptr;
}
@@ -139,7 +139,7 @@ OptionValue::GetAsArray () const
{
if (GetType () == OptionValue::eTypeArray)
return static_cast<const OptionValueArray *>(this);
- return NULL;
+ return nullptr;
}
OptionValueArgs *
@@ -147,7 +147,7 @@ OptionValue::GetAsArgs ()
{
if (GetType () == OptionValue::eTypeArgs)
return static_cast<OptionValueArgs *>(this);
- return NULL;
+ return nullptr;
}
@@ -156,7 +156,7 @@ OptionValue::GetAsArgs () const
{
if (GetType () == OptionValue::eTypeArgs)
return static_cast<const OptionValueArgs *>(this);
- return NULL;
+ return nullptr;
}
OptionValueDictionary *
@@ -164,7 +164,7 @@ OptionValue::GetAsDictionary ()
{
if (GetType () == OptionValue::eTypeDictionary)
return static_cast<OptionValueDictionary *>(this);
- return NULL;
+ return nullptr;
}
const OptionValueDictionary *
@@ -172,7 +172,7 @@ OptionValue::GetAsDictionary () const
{
if (GetType () == OptionValue::eTypeDictionary)
return static_cast<const OptionValueDictionary *>(this);
- return NULL;
+ return nullptr;
}
OptionValueEnumeration *
@@ -180,7 +180,7 @@ OptionValue::GetAsEnumeration ()
{
if (GetType () == OptionValue::eTypeEnum)
return static_cast<OptionValueEnumeration *>(this);
- return NULL;
+ return nullptr;
}
const OptionValueEnumeration *
@@ -188,7 +188,7 @@ OptionValue::GetAsEnumeration () const
{
if (GetType () == OptionValue::eTypeEnum)
return static_cast<const OptionValueEnumeration *>(this);
- return NULL;
+ return nullptr;
}
OptionValueFormat *
@@ -196,7 +196,7 @@ OptionValue::GetAsFormat ()
{
if (GetType () == OptionValue::eTypeFormat)
return static_cast<OptionValueFormat *>(this);
- return NULL;
+ return nullptr;
}
const OptionValueFormat *
@@ -204,7 +204,7 @@ OptionValue::GetAsFormat () const
{
if (GetType () == OptionValue::eTypeFormat)
return static_cast<const OptionValueFormat *>(this);
- return NULL;
+ return nullptr;
}
OptionValuePathMappings *
@@ -212,7 +212,7 @@ OptionValue::GetAsPathMappings ()
{
if (GetType () == OptionValue::eTypePathMap)
return static_cast<OptionValuePathMappings *>(this);
- return NULL;
+ return nullptr;
}
const OptionValuePathMappings *
@@ -220,7 +220,7 @@ OptionValue::GetAsPathMappings () const
{
if (GetType () == OptionValue::eTypePathMap)
return static_cast<const OptionValuePathMappings *>(this);
- return NULL;
+ return nullptr;
}
OptionValueProperties *
@@ -228,7 +228,7 @@ OptionValue::GetAsProperties ()
{
if (GetType () == OptionValue::eTypeProperties)
return static_cast<OptionValueProperties *>(this);
- return NULL;
+ return nullptr;
}
const OptionValueProperties *
@@ -236,7 +236,7 @@ OptionValue::GetAsProperties () const
{
if (GetType () == OptionValue::eTypeProperties)
return static_cast<const OptionValueProperties *>(this);
- return NULL;
+ return nullptr;
}
OptionValueRegex *
@@ -244,7 +244,7 @@ OptionValue::GetAsRegex ()
{
if (GetType () == OptionValue::eTypeRegex)
return static_cast<OptionValueRegex *>(this);
- return NULL;
+ return nullptr;
}
const OptionValueRegex *
@@ -252,7 +252,7 @@ OptionValue::GetAsRegex () const
{
if (GetType () == OptionValue::eTypeRegex)
return static_cast<const OptionValueRegex *>(this);
- return NULL;
+ return nullptr;
}
OptionValueSInt64 *
@@ -260,7 +260,7 @@ OptionValue::GetAsSInt64 ()
{
if (GetType () == OptionValue::eTypeSInt64)
return static_cast<OptionValueSInt64 *>(this);
- return NULL;
+ return nullptr;
}
const OptionValueSInt64 *
@@ -268,7 +268,7 @@ OptionValue::GetAsSInt64 () const
{
if (GetType () == OptionValue::eTypeSInt64)
return static_cast<const OptionValueSInt64 *>(this);
- return NULL;
+ return nullptr;
}
OptionValueString *
@@ -276,7 +276,7 @@ OptionValue::GetAsString ()
{
if (GetType () == OptionValue::eTypeString)
return static_cast<OptionValueString *>(this);
- return NULL;
+ return nullptr;
}
const OptionValueString *
@@ -284,7 +284,7 @@ OptionValue::GetAsString () const
{
if (GetType () == OptionValue::eTypeString)
return static_cast<const OptionValueString *>(this);
- return NULL;
+ return nullptr;
}
OptionValueUInt64 *
@@ -292,7 +292,7 @@ OptionValue::GetAsUInt64 ()
{
if (GetType () == OptionValue::eTypeUInt64)
return static_cast<OptionValueUInt64 *>(this);
- return NULL;
+ return nullptr;
}
const OptionValueUInt64 *
@@ -300,7 +300,7 @@ OptionValue::GetAsUInt64 () const
{
if (GetType () == OptionValue::eTypeUInt64)
return static_cast<const OptionValueUInt64 *>(this);
- return NULL;
+ return nullptr;
}
OptionValueUUID *
@@ -308,7 +308,7 @@ OptionValue::GetAsUUID ()
{
if (GetType () == OptionValue::eTypeUUID)
return static_cast<OptionValueUUID *>(this);
- return NULL;
+ return nullptr;
}
@@ -317,7 +317,7 @@ OptionValue::GetAsUUID () const
{
if (GetType () == OptionValue::eTypeUUID)
return static_cast<const OptionValueUUID *>(this);
- return NULL;
+ return nullptr;
}
@@ -422,7 +422,7 @@ OptionValue::GetRegexValue () const
const OptionValueRegex *option_value = GetAsRegex ();
if (option_value)
return option_value->GetCurrentValue();
- return NULL;
+ return nullptr;
}
@@ -533,7 +533,7 @@ OptionValue::GetBuiltinTypeAsCString (Type t)
case eTypeUInt64: return "unsigned";
case eTypeUUID: return "uuid";
}
- return NULL;
+ return nullptr;
}
diff --git a/source/Interpreter/OptionValueArch.cpp b/source/Interpreter/OptionValueArch.cpp
index 92fedffe75ea..6d283d6b9275 100644
--- a/source/Interpreter/OptionValueArch.cpp
+++ b/source/Interpreter/OptionValueArch.cpp
@@ -100,7 +100,7 @@ OptionValueArch::AutoComplete (CommandInterpreter &interpreter,
s,
match_start_point,
max_return_elements,
- NULL,
+ nullptr,
word_complete,
matches);
return matches.GetSize();
diff --git a/source/Interpreter/OptionValueArray.cpp b/source/Interpreter/OptionValueArray.cpp
index 9a015580bd6c..769aadd7b308 100644
--- a/source/Interpreter/OptionValueArray.cpp
+++ b/source/Interpreter/OptionValueArray.cpp
@@ -90,12 +90,12 @@ OptionValueArray::GetSubValue (const ExecutionContext *exe_ctx,
const char *end_bracket = strchr (name+1, ']');
if (end_bracket)
{
- const char *sub_value = NULL;
+ const char *sub_value = nullptr;
if (end_bracket[1])
sub_value = end_bracket + 1;
std::string index_str (name+1, end_bracket);
const size_t array_count = m_values.size();
- int32_t idx = Args::StringToSInt32(index_str.c_str(), INT32_MAX, 0, NULL);
+ int32_t idx = Args::StringToSInt32(index_str.c_str(), INT32_MAX, 0, nullptr);
if (idx != INT32_MAX)
{
;
@@ -222,7 +222,8 @@ OptionValueArray::SetArgs (const Args &args, VarSetOperationType op)
size_t i;
for (i=0; i<argc; ++i)
{
- const int idx = Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
+ const size_t idx =
+ Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
if (idx >= size)
{
all_indexes_valid = false;
diff --git a/source/Interpreter/OptionValueBoolean.cpp b/source/Interpreter/OptionValueBoolean.cpp
index 6471943ee5dc..bf153a1442c7 100644
--- a/source/Interpreter/OptionValueBoolean.cpp
+++ b/source/Interpreter/OptionValueBoolean.cpp
@@ -16,6 +16,7 @@
#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;
@@ -58,7 +59,7 @@ OptionValueBoolean::SetValueFromCString (const char *value_cstr,
}
else
{
- if (value_cstr == NULL)
+ if (value_cstr == nullptr)
error.SetErrorString ("invalid boolean string value: NULL");
else if (value_cstr[0] == '\0')
error.SetErrorString ("invalid boolean string value <empty>");
@@ -110,7 +111,7 @@ OptionValueBoolean::AutoComplete (CommandInterpreter &interpreter,
{ "1" , 1 },
{ "0" , 1 },
};
- const size_t k_num_autocomplete_entries = sizeof(g_autocomplete_entries)/sizeof(StringEntry);
+ const size_t k_num_autocomplete_entries = llvm::array_lengthof(g_autocomplete_entries);
if (s && s[0])
{
diff --git a/source/Interpreter/OptionValueDictionary.cpp b/source/Interpreter/OptionValueDictionary.cpp
index 61f8aba431ac..b560937141b3 100644
--- a/source/Interpreter/OptionValueDictionary.cpp
+++ b/source/Interpreter/OptionValueDictionary.cpp
@@ -91,7 +91,7 @@ OptionValueDictionary::GetArgs (Args &args) const
{
StreamString strm;
strm.Printf("%s=", pos->first.GetCString());
- pos->second->DumpValue(NULL, strm, eDumpOptionValue|eDumpOptionRaw);
+ pos->second->DumpValue(nullptr, strm, eDumpOptionValue|eDumpOptionRaw);
args.AppendArgument(strm.GetString().c_str());
}
return args.GetArgumentCount();
@@ -210,7 +210,7 @@ OptionValueDictionary::SetArgs (const Args &args, VarSetOperationType op)
case eVarSetOperationInsertBefore:
case eVarSetOperationInsertAfter:
case eVarSetOperationInvalid:
- error = OptionValue::SetValueFromCString (NULL, op);
+ error = OptionValue::SetValueFromCString (nullptr, op);
break;
}
return error;
@@ -230,14 +230,14 @@ OptionValueDictionary::GetSubValue (const ExecutionContext *exe_ctx, const char
if (name && name[0])
{
- const char *sub_name = NULL;
+ const char *sub_name = nullptr;
ConstString key;
const char *open_bracket = ::strchr (name, '[');
if (open_bracket)
{
const char *key_start = open_bracket + 1;
- const char *key_end = NULL;
+ const char *key_end = nullptr;
switch (open_bracket[1])
{
case '\'':
@@ -314,7 +314,7 @@ OptionValueDictionary::GetSubValue (const ExecutionContext *exe_ctx, const char
}
}
}
- if (!value_sp && error.AsCString() == NULL)
+ if (!value_sp && error.AsCString() == nullptr)
{
error.SetErrorStringWithFormat ("invalid value path '%s', %s values only support '[<key>]' subvalues where <key> a string value optionally delimitted by single or double quotes",
name,
@@ -334,7 +334,7 @@ OptionValueDictionary::SetSubValue (const ExecutionContext *exe_ctx, VarSetOpera
error = value_sp->SetValueFromCString(value, op);
else
{
- if (error.AsCString() == NULL)
+ if (error.AsCString() == nullptr)
error.SetErrorStringWithFormat("invalid value path '%s'", name);
}
return error;
@@ -361,7 +361,7 @@ OptionValueDictionary::GetStringValueForKey (const ConstString &key)
if (string_value)
return string_value->GetCurrentValue();
}
- return NULL;
+ return nullptr;
}
diff --git a/source/Interpreter/OptionValueEnumeration.cpp b/source/Interpreter/OptionValueEnumeration.cpp
index f282235d58e3..7aceac91b601 100644
--- a/source/Interpreter/OptionValueEnumeration.cpp
+++ b/source/Interpreter/OptionValueEnumeration.cpp
@@ -113,7 +113,7 @@ OptionValueEnumeration::SetEnumerations (const OptionEnumValueElement *enumerato
m_enumerations.Clear();
if (enumerators)
{
- for (size_t i=0; enumerators[i].string_value != NULL; ++i)
+ for (size_t i=0; enumerators[i].string_value != nullptr; ++i)
{
ConstString const_enumerator_name(enumerators[i].string_value);
EnumeratorInfo enumerator_info = { enumerators[i].value, enumerators[i].usage };
diff --git a/source/Interpreter/OptionValueFileSpec.cpp b/source/Interpreter/OptionValueFileSpec.cpp
index 3d2a7ff3307a..c8aaadef23bc 100644
--- a/source/Interpreter/OptionValueFileSpec.cpp
+++ b/source/Interpreter/OptionValueFileSpec.cpp
@@ -99,6 +99,7 @@ OptionValueFileSpec::SetValueFromCString (const char *value_cstr,
m_value_was_set = true;
m_current_value.SetFile(filepath.c_str(), true);
+ m_data_sp.reset();
}
else
{
@@ -139,7 +140,7 @@ OptionValueFileSpec::AutoComplete (CommandInterpreter &interpreter,
s,
match_start_point,
max_return_elements,
- NULL,
+ nullptr,
word_complete,
matches);
return matches.GetSize();
diff --git a/source/Interpreter/OptionValueFormat.cpp b/source/Interpreter/OptionValueFormat.cpp
index 34d36725fbbe..296dd983208c 100644
--- a/source/Interpreter/OptionValueFormat.cpp
+++ b/source/Interpreter/OptionValueFormat.cpp
@@ -49,7 +49,7 @@ OptionValueFormat::SetValueFromCString (const char *value_cstr, VarSetOperationT
case eVarSetOperationAssign:
{
Format new_format;
- error = Args::StringToFormat (value_cstr, new_format, NULL);
+ error = Args::StringToFormat (value_cstr, new_format, nullptr);
if (error.Success())
{
m_value_was_set = true;
diff --git a/source/Interpreter/OptionValueProperties.cpp b/source/Interpreter/OptionValueProperties.cpp
index abee55d93efa..0497ee1c15d7 100644
--- a/source/Interpreter/OptionValueProperties.cpp
+++ b/source/Interpreter/OptionValueProperties.cpp
@@ -35,6 +35,7 @@ OptionValueProperties::OptionValueProperties (const ConstString &name) :
OptionValueProperties::OptionValueProperties (const OptionValueProperties &global_properties) :
OptionValue (global_properties),
+ std::enable_shared_from_this<OptionValueProperties> (),
m_name (global_properties.m_name),
m_properties (global_properties.m_properties),
m_name_to_index (global_properties.m_name_to_index)
@@ -46,7 +47,7 @@ OptionValueProperties::OptionValueProperties (const OptionValueProperties &globa
const size_t num_properties = m_properties.size();
for (size_t i=0; i<num_properties; ++i)
{
- // Duplicate any values that are not global when contructing properties from
+ // Duplicate any values that are not global when constructing properties from
// a global copy
if (m_properties[i].IsGlobal() == false)
{
@@ -135,7 +136,7 @@ OptionValueProperties::GetSubValue (const ExecutionContext *exe_ctx,
if (name && name[0])
{
- const char *sub_name = NULL;
+ const char *sub_name = nullptr;
ConstString key;
size_t key_len = ::strcspn (name, ".[{");
@@ -163,7 +164,7 @@ OptionValueProperties::GetSubValue (const ExecutionContext *exe_ctx,
// OptionValueProperties for a lldb_private::Target might implement:
// "target.run-args{arch==i386}" -- only set run args if the arch is i386
// "target.run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the path matches
- // "target.run-args{basename==test&&arch==x86_64}" -- only set run args if exectable basename is "test" and arch is "x86_64"
+ // "target.run-args{basename==test&&arch==x86_64}" -- only set run args if executable basename is "test" and arch is "x86_64"
if (sub_name[1])
{
const char *predicate_start = sub_name + 1;
@@ -218,7 +219,7 @@ OptionValueProperties::SetSubValue (const ExecutionContext *exe_ctx,
error = value_sp->SetValueFromCString(value, op);
else
{
- if (error.AsCString() == NULL)
+ if (error.AsCString() == nullptr)
error.SetErrorStringWithFormat("invalid value path '%s'", name);
}
return error;
@@ -228,7 +229,7 @@ OptionValueProperties::SetSubValue (const ExecutionContext *exe_ctx,
ConstString
OptionValueProperties::GetPropertyNameAtIndex (uint32_t idx) const
{
- const Property *property = GetPropertyAtIndex(NULL, false, idx);
+ const Property *property = GetPropertyAtIndex(nullptr, false, idx);
if (property)
return property->GetName();
return ConstString();
@@ -238,10 +239,10 @@ OptionValueProperties::GetPropertyNameAtIndex (uint32_t idx) const
const char *
OptionValueProperties::GetPropertyDescriptionAtIndex (uint32_t idx) const
{
- const Property *property = GetPropertyAtIndex(NULL, false, idx);
+ const Property *property = GetPropertyAtIndex(nullptr, false, idx);
if (property)
return property->GetDescription();
- return NULL;
+ return nullptr;
}
uint32_t
@@ -279,7 +280,7 @@ OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings (const Execut
OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx));
if (value_sp)
return value_sp->GetAsPathMappings();
- return NULL;
+ return nullptr;
}
OptionValueFileSpecList *
@@ -288,7 +289,7 @@ OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList (const Execut
OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx));
if (value_sp)
return value_sp->GetAsFileSpecList();
- return NULL;
+ return nullptr;
}
OptionValueArch *
@@ -297,7 +298,7 @@ OptionValueProperties::GetPropertyAtIndexAsOptionValueArch (const ExecutionConte
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
return property->GetValue()->GetAsArch();
- return NULL;
+ return nullptr;
}
bool
@@ -381,7 +382,7 @@ OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary (const Executio
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
return property->GetValue()->GetAsDictionary();
- return NULL;
+ return nullptr;
}
int64_t
@@ -421,7 +422,7 @@ OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec (const ExecutionC
if (value)
return value->GetAsFileSpec();
}
- return NULL;
+ return nullptr;
}
@@ -462,7 +463,7 @@ OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex (const ExecutionCont
if (value)
return value->GetRegexValue();
}
- return NULL;
+ return nullptr;
}
OptionValueSInt64 *
@@ -475,7 +476,7 @@ OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64 (const ExecutionCon
if (value)
return value->GetAsSInt64();
}
- return NULL;
+ return nullptr;
}
int64_t
@@ -536,7 +537,7 @@ OptionValueProperties::GetPropertyAtIndexAsOptionValueString (const ExecutionCon
OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx));
if (value_sp)
return value_sp->GetAsString();
- return NULL;
+ return nullptr;
}
@@ -659,10 +660,10 @@ OptionValueProperties::GetPropertyAtPath (const ExecutionContext *exe_ctx,
bool will_modify,
const char *name) const
{
- const Property *property = NULL;
+ const Property *property = nullptr;
if (name && name[0])
{
- const char *sub_name = NULL;
+ const char *sub_name = nullptr;
ConstString key;
size_t key_len = ::strcspn (name, ".[{");
@@ -683,7 +684,7 @@ OptionValueProperties::GetPropertyAtPath (const ExecutionContext *exe_ctx,
if (sub_properties)
return sub_properties->GetPropertyAtPath(exe_ctx, will_modify, sub_name + 1);
}
- property = NULL;
+ property = nullptr;
}
}
return property;
diff --git a/source/Interpreter/OptionValueUUID.cpp b/source/Interpreter/OptionValueUUID.cpp
index 340f1e5e9986..0141911d97ad 100644
--- a/source/Interpreter/OptionValueUUID.cpp
+++ b/source/Interpreter/OptionValueUUID.cpp
@@ -92,7 +92,7 @@ OptionValueUUID::AutoComplete (CommandInterpreter &interpreter,
if (num_modules > 0)
{
UUID::ValueType uuid_bytes;
- const size_t num_bytes_decoded = UUID::DecodeUUIDBytesFromCString(s, uuid_bytes, NULL);
+ const size_t num_bytes_decoded = UUID::DecodeUUIDBytesFromCString(s, uuid_bytes, nullptr);
for (size_t i=0; i<num_modules; ++i)
{
ModuleSP module_sp (target->GetImages().GetModuleAtIndex(i));
diff --git a/source/Interpreter/Options.cpp b/source/Interpreter/Options.cpp
index c6c66d8ac650..a8766f5f8615 100644
--- a/source/Interpreter/Options.cpp
+++ b/source/Interpreter/Options.cpp
@@ -242,14 +242,14 @@ uint32_t
Options::NumCommandOptions ()
{
const OptionDefinition *opt_defs = GetDefinitions ();
- if (opt_defs == NULL)
+ if (opt_defs == nullptr)
return 0;
int i = 0;
- if (opt_defs != NULL)
+ if (opt_defs != nullptr)
{
- while (opt_defs[i].long_option != NULL)
+ while (opt_defs[i].long_option != nullptr)
++i;
}
@@ -265,7 +265,7 @@ Options::GetLongOptions ()
// Check to see if there are any options.
const uint32_t num_options = NumCommandOptions();
if (num_options == 0)
- return NULL;
+ return nullptr;
uint32_t i;
const OptionDefinition *opt_defs = GetDefinitions();
@@ -277,9 +277,8 @@ Options::GetLongOptions ()
{
const int short_opt = opt_defs[i].short_option;
- m_getopt_table[i].name = opt_defs[i].long_option;
- m_getopt_table[i].has_arg = opt_defs[i].option_has_arg;
- m_getopt_table[i].flag = NULL;
+ m_getopt_table[i].definition = &opt_defs[i];
+ m_getopt_table[i].flag = nullptr;
m_getopt_table[i].val = short_opt;
if (option_seen.find(short_opt) == option_seen.end())
@@ -297,7 +296,7 @@ Options::GetLongOptions ()
opt_defs[i].long_option,
short_opt,
pos->second,
- m_getopt_table[pos->second].name,
+ m_getopt_table[pos->second].definition->long_option,
opt_defs[i].long_option);
else
Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option 0x%x that conflicts with option[%u] --%s, short option won't be used for --%s\n",
@@ -305,21 +304,20 @@ Options::GetLongOptions ()
opt_defs[i].long_option,
short_opt,
pos->second,
- m_getopt_table[pos->second].name,
+ m_getopt_table[pos->second].definition->long_option,
opt_defs[i].long_option);
}
}
//getopt_long_only requires a NULL final entry in the table:
- m_getopt_table[i].name = NULL;
- m_getopt_table[i].has_arg = 0;
- m_getopt_table[i].flag = NULL;
- m_getopt_table[i].val = 0;
+ m_getopt_table[i].definition = nullptr;
+ m_getopt_table[i].flag = nullptr;
+ m_getopt_table[i].val = 0;
}
if (m_getopt_table.empty())
- return NULL;
+ return nullptr;
return &m_getopt_table.front();
}
@@ -336,18 +334,29 @@ void
Options::OutputFormattedUsageText
(
Stream &strm,
- const char *text,
+ const OptionDefinition &option_def,
uint32_t output_max_columns
)
{
- int len = strlen (text);
+ std::string actual_text;
+ if (option_def.validator)
+ {
+ const char *condition = option_def.validator->ShortConditionString();
+ if (condition)
+ {
+ actual_text = "[";
+ actual_text.append(condition);
+ actual_text.append("] ");
+ }
+ }
+ actual_text.append(option_def.usage_text);
// Will it all fit on one line?
- if ((len + strm.GetIndentLevel()) < output_max_columns)
+ if (static_cast<uint32_t>(actual_text.length() + strm.GetIndentLevel()) < output_max_columns)
{
// Output it as a single line.
- strm.Indent (text);
+ strm.Indent (actual_text.c_str());
strm.EOL();
}
else
@@ -357,13 +366,13 @@ Options::OutputFormattedUsageText
int text_width = output_max_columns - strm.GetIndentLevel() - 1;
int start = 0;
int end = start;
- int final_end = strlen (text);
+ int final_end = actual_text.length();
int sub_len;
while (end < final_end)
{
// Don't start the 'text' on a space, since we're already outputting the indentation.
- while ((start < final_end) && (text[start] == ' '))
+ while ((start < final_end) && (actual_text[start] == ' '))
start++;
end = start + text_width;
@@ -373,7 +382,7 @@ Options::OutputFormattedUsageText
{
// 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')
+ && actual_text[end] != ' ' && actual_text[end] != '\t' && actual_text[end] != '\n')
end--;
}
@@ -383,7 +392,7 @@ Options::OutputFormattedUsageText
strm.Indent();
assert (start < final_end);
assert (start + sub_len <= final_end);
- strm.Write(text + start, sub_len);
+ strm.Write(actual_text.c_str() + start, sub_len);
start = end + 1;
}
strm.EOL();
@@ -592,7 +601,7 @@ Options::GenerateOptionUsage
if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
{
if (opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument)
- PrintOption (opt_defs[i], eDisplayBestOption, " ", NULL, true, strm);
+ PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm);
}
}
@@ -605,7 +614,7 @@ Options::GenerateOptionUsage
// Add current option to the end of out_stream.
if (!opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument)
- PrintOption (opt_defs[i], eDisplayBestOption, " ", NULL, true, strm);
+ PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm);
}
}
@@ -630,7 +639,7 @@ Options::GenerateOptionUsage
strm.Printf ("\n\n");
// Now print out all the detailed information about the various options: long form, short form and help text:
- // --long_name <argument> ( -short <argument> )
+ // -short <argument> ( --long_name <argument> )
// help text
// This variable is used to keep track of which options' info we've printed out, because some options can be in
@@ -669,13 +678,13 @@ Options::GenerateOptionUsage
strm.Indent ();
if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option))
{
- PrintOption (opt_defs[i], eDisplayShortOption, NULL, NULL, false, strm);
+ PrintOption (opt_defs[i], eDisplayShortOption, nullptr, nullptr, false, strm);
PrintOption (opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm);
}
else
{
// Short option is not printable, just print long option
- PrintOption (opt_defs[i], eDisplayLongOption, NULL, NULL, false, strm);
+ PrintOption (opt_defs[i], eDisplayLongOption, nullptr, nullptr, false, strm);
}
strm.EOL();
@@ -683,13 +692,13 @@ Options::GenerateOptionUsage
if (opt_defs[i].usage_text)
OutputFormattedUsageText (strm,
- opt_defs[i].usage_text,
+ opt_defs[i],
screen_width);
- if (opt_defs[i].enum_values != NULL)
+ if (opt_defs[i].enum_values != nullptr)
{
strm.Indent ();
strm.Printf("Values: ");
- for (int k = 0; opt_defs[i].enum_values[k].string_value != NULL; k++)
+ for (int k = 0; opt_defs[i].enum_values[k].string_value != nullptr; k++)
{
if (k == 0)
strm.Printf("%s", opt_defs[i].enum_values[k].string_value);
@@ -908,11 +917,11 @@ Options::HandleOptionArgumentCompletion
// See if this is an enumeration type option, and if so complete it here:
OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
- if (enum_values != NULL)
+ if (enum_values != nullptr)
{
bool return_value = false;
std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
- for (int i = 0; enum_values[i].string_value != NULL; i++)
+ for (int i = 0; enum_values[i].string_value != nullptr; i++)
{
if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
{
@@ -1001,7 +1010,7 @@ OptionGroupOptions::GetGroupWithOption (char short_opt)
if (opt_def.short_option == short_opt)
return m_option_infos[i].option_group;
}
- return NULL;
+ return nullptr;
}
void
@@ -1026,7 +1035,7 @@ void
OptionGroupOptions::Finalize ()
{
m_did_finalize = true;
- OptionDefinition empty_option_def = { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL };
+ OptionDefinition empty_option_def = { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr };
m_option_defs.push_back (empty_option_def);
}
diff --git a/source/Interpreter/Property.cpp b/source/Interpreter/Property.cpp
index e5cf63ada882..49376266b077 100644
--- a/source/Interpreter/Property.cpp
+++ b/source/Interpreter/Property.cpp
@@ -56,7 +56,7 @@ Property::Property (const PropertyDefinition &definition) :
// "definition.default_cstr_value" as a string value that represents the default
// value.
if (definition.default_cstr_value)
- m_value_sp.reset (new OptionValueBoolean(Args::StringToBoolean (definition.default_cstr_value, false, NULL)));
+ m_value_sp.reset (new OptionValueBoolean(Args::StringToBoolean (definition.default_cstr_value, false, nullptr)));
else
m_value_sp.reset (new OptionValueBoolean(definition.default_uint_value != 0));
break;
@@ -108,7 +108,7 @@ Property::Property (const PropertyDefinition &definition) :
{
Format new_format = eFormatInvalid;
if (definition.default_cstr_value)
- Args::StringToFormat (definition.default_cstr_value, new_format, NULL);
+ Args::StringToFormat (definition.default_cstr_value, new_format, nullptr);
else
new_format = (Format)definition.default_uint_value;
m_value_sp.reset (new OptionValueFormat(new_format));
diff --git a/source/Interpreter/PythonDataObjects.cpp b/source/Interpreter/PythonDataObjects.cpp
index 053ff34b9d77..3ea6c0dbe3e5 100644
--- a/source/Interpreter/PythonDataObjects.cpp
+++ b/source/Interpreter/PythonDataObjects.cpp
@@ -31,7 +31,7 @@ using namespace lldb;
// PythonObject
//----------------------------------------------------------------------
PythonObject::PythonObject (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
- m_py_obj (NULL)
+ m_py_obj (nullptr)
{
if (script_object_sp)
Reset ((PyObject *)script_object_sp->GetObject());
@@ -133,8 +133,8 @@ PythonString::Reset (PyObject *py_obj)
if (py_obj && PyString_Check(py_obj))
return PythonObject::Reset(py_obj);
- PythonObject::Reset(NULL);
- return py_obj == NULL;
+ PythonObject::Reset(nullptr);
+ return py_obj == nullptr;
}
const char*
@@ -142,7 +142,7 @@ PythonString::GetString() const
{
if (m_py_obj)
return PyString_AsString(m_py_obj);
- return NULL;
+ return nullptr;
}
size_t
@@ -202,8 +202,8 @@ PythonInteger::Reset (PyObject *py_obj)
return PythonObject::Reset(py_obj);
}
- PythonObject::Reset(NULL);
- return py_obj == NULL;
+ PythonObject::Reset(nullptr);
+ return py_obj == nullptr;
}
int64_t
@@ -230,7 +230,7 @@ PythonInteger::SetInteger (int64_t value)
//----------------------------------------------------------------------
PythonList::PythonList (bool create_empty) :
- PythonObject(create_empty ? PyList_New(0) : NULL)
+ PythonObject(create_empty ? PyList_New(0) : nullptr)
{
}
@@ -269,8 +269,8 @@ PythonList::Reset (PyObject *py_obj)
if (py_obj && PyList_Check(py_obj))
return PythonObject::Reset(py_obj);
- PythonObject::Reset(NULL);
- return py_obj == NULL;
+ PythonObject::Reset(nullptr);
+ return py_obj == nullptr;
}
uint32_t
@@ -308,7 +308,7 @@ PythonList::AppendItem (const PythonObject &object)
//----------------------------------------------------------------------
PythonDictionary::PythonDictionary (bool create_empty) :
-PythonObject(create_empty ? PyDict_New() : NULL)
+PythonObject(create_empty ? PyDict_New() : nullptr)
{
}
@@ -342,8 +342,8 @@ PythonDictionary::Reset (PyObject *py_obj)
if (py_obj && PyDict_Check(py_obj))
return PythonObject::Reset(py_obj);
- PythonObject::Reset(NULL);
- return py_obj == NULL;
+ PythonObject::Reset(nullptr);
+ return py_obj == nullptr;
}
uint32_t
diff --git a/source/Interpreter/ScriptInterpreter.cpp b/source/Interpreter/ScriptInterpreter.cpp
index 1b751afb135e..b6c46f83bd92 100644
--- a/source/Interpreter/ScriptInterpreter.cpp
+++ b/source/Interpreter/ScriptInterpreter.cpp
@@ -44,7 +44,7 @@ ScriptInterpreter::GetCommandInterpreter ()
void
ScriptInterpreter::CollectDataForBreakpointCommandCallback
(
- BreakpointOptions *bp_options,
+ std::vector<BreakpointOptions *> &bp_options_vec,
CommandReturnObject &result
)
{
@@ -81,6 +81,30 @@ ScriptInterpreter::LanguageToString (lldb::ScriptLanguage language)
return return_value;
}
+Error
+ScriptInterpreter::SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
+ const char *callback_text)
+{
+ Error return_error;
+ for (BreakpointOptions *bp_options : bp_options_vec)
+ {
+ return_error = SetBreakpointCommandCallback(bp_options, callback_text);
+ if (return_error.Success())
+ break;
+ }
+ return return_error;
+}
+
+void
+ScriptInterpreter::SetBreakpointCommandCallbackFunction (std::vector<BreakpointOptions *> &bp_options_vec,
+ const char *function_name)
+{
+ for (BreakpointOptions *bp_options : bp_options_vec)
+ {
+ SetBreakpointCommandCallbackFunction(bp_options, function_name);
+ }
+}
+
std::unique_ptr<ScriptInterpreterLocker>
ScriptInterpreter::AcquireInterpreterLock ()
{
@@ -132,12 +156,3 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call
swig_plugin_get);
#endif // #ifndef LLDB_DISABLE_PYTHON
}
-
-void
-ScriptInterpreter::TerminateInterpreter ()
-{
-#ifndef LLDB_DISABLE_PYTHON
- ScriptInterpreterPython::TerminateInterpreter ();
-#endif // #ifndef LLDB_DISABLE_PYTHON
-}
-
diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp
index c1d28e88afc1..1b24fea7c218 100644
--- a/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/source/Interpreter/ScriptInterpreterPython.cpp
@@ -31,7 +31,8 @@
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Timer.h"
-#include "lldb/Host/Host.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"
@@ -41,33 +42,26 @@ using namespace lldb;
using namespace lldb_private;
-static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = NULL;
-static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = NULL;
-static ScriptInterpreter::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = NULL;
-static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = NULL;
-static ScriptInterpreter::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = NULL;
-static ScriptInterpreter::SWIGPythonCalculateNumChildren g_swig_calc_children = NULL;
-static ScriptInterpreter::SWIGPythonGetChildAtIndex g_swig_get_child_index = NULL;
-static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = NULL;
-static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = NULL;
-static ScriptInterpreter::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = NULL;
-static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = NULL;
-static ScriptInterpreter::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = NULL;
-static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = NULL;
-static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = NULL;
-static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = NULL;
-static ScriptInterpreter::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = NULL;
-static ScriptInterpreter::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = NULL;
-static ScriptInterpreter::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = NULL;
-static ScriptInterpreter::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = NULL;
-static ScriptInterpreter::SWIGPython_GetDynamicSetting g_swig_plugin_get = NULL;
-
-static int
-_check_and_flush (FILE *stream)
-{
- int prev_fail = ferror (stream);
- return fflush (stream) || prev_fail ? EOF : 0;
-}
+static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = nullptr;
+static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = nullptr;
+static ScriptInterpreter::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = nullptr;
+static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = nullptr;
+static ScriptInterpreter::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = nullptr;
+static ScriptInterpreter::SWIGPythonCalculateNumChildren g_swig_calc_children = nullptr;
+static ScriptInterpreter::SWIGPythonGetChildAtIndex g_swig_get_child_index = nullptr;
+static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = nullptr;
+static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = nullptr;
+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::SWIGPythonCallCommand g_swig_call_command = nullptr;
+static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr;
+static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr;
+static ScriptInterpreter::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = nullptr;
+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::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr;
static std::string
ReadPythonBacktrace (PyObject* py_backtrace);
@@ -100,6 +94,13 @@ ScriptInterpreterPython::Locker::DoAcquireLock()
m_GILState = PyGILState_Ensure();
if (log)
log->Printf("Ensured PyGILState. Previous state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : "");
+
+ // we need to save the thread state when we first start the command
+ // because we might decide to interrupt it while some action is taking
+ // place outside of Python (e.g. printing to screen, waiting for the network, ...)
+ // in that case, _PyThreadState_Current will be NULL - and we would be unable
+ // to set the asynchronous exception - not a desirable situation
+ m_python_interpreter->SetThreadState (_PyThreadState_Current);
return true;
}
@@ -156,7 +157,7 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete
m_session_is_active (false),
m_pty_slave_is_open (false),
m_valid_session (true),
- m_command_thread_state (NULL)
+ m_command_thread_state (nullptr)
{
ScriptInterpreterPython::InitializePrivate ();
@@ -213,7 +214,7 @@ ScriptInterpreterPython::~ScriptInterpreterPython ()
void
ScriptInterpreterPython::IOHandlerActivated (IOHandler &io_handler)
{
- const char *instructions = NULL;
+ const char *instructions = nullptr;
switch (m_active_io_handler)
{
@@ -255,24 +256,30 @@ ScriptInterpreterPython::IOHandlerInputComplete (IOHandler &io_handler, std::str
break;
case eIOHandlerBreakpoint:
{
- BreakpointOptions *bp_options = (BreakpointOptions *)io_handler.GetUserData();
- std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
- if (data_ap.get())
+ std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
+ for (auto bp_options : *bp_options_vec)
{
- data_ap->user_source.SplitIntoLines(data);
-
- if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source))
+ if (!bp_options)
+ continue;
+
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+ if (data_ap.get())
{
- BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
- bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
- }
- else if (!batch_mode)
- {
- StreamFileSP error_sp = io_handler.GetErrorStreamFile();
- if (error_sp)
+ data_ap->user_source.SplitIntoLines(data);
+
+ if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source).Success())
{
- error_sp->Printf ("Warning: No command attached to breakpoint.\n");
- error_sp->Flush();
+ BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+ bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
+ }
+ else if (!batch_mode)
+ {
+ StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+ if (error_sp)
+ {
+ error_sp->Printf ("Warning: No command attached to breakpoint.\n");
+ error_sp->Flush();
+ }
}
}
}
@@ -306,8 +313,6 @@ ScriptInterpreterPython::IOHandlerInputComplete (IOHandler &io_handler, std::str
}
break;
}
-
-
}
@@ -427,42 +432,42 @@ ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags,
lldb::StreamFileSP in_sp;
lldb::StreamFileSP out_sp;
lldb::StreamFileSP err_sp;
- if (in == NULL || out == NULL || err == NULL)
+ if (in == nullptr || out == nullptr || err == nullptr)
m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid (in_sp, out_sp, err_sp);
- if (in == NULL && in_sp && (on_entry_flags & Locker::NoSTDIN) == 0)
+ 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"));
- PyObject *new_file = PyFile_FromFile (in, (char *) "", (char *) "r", 0);
+ 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 == NULL && out_sp)
+ if (out == nullptr && out_sp)
out = out_sp->GetFile().GetStream();
if (out)
{
m_saved_stdout.Reset(sys_module_dict.GetItemForKey("stdout"));
- PyObject *new_file = PyFile_FromFile (out, (char *) "", (char *) "w", 0);
+ PyObject *new_file = PyFile_FromFile (out, (char *) "", (char *) "w", nullptr);
sys_module_dict.SetItemForKey ("stdout", new_file);
Py_DECREF (new_file);
}
else
m_saved_stdout.Reset();
- if (err == NULL && err_sp)
+ if (err == nullptr && err_sp)
err = err_sp->GetFile().GetStream();
if (err)
{
m_saved_stderr.Reset(sys_module_dict.GetItemForKey("stderr"));
- PyObject *new_file = PyFile_FromFile (err, (char *) "", (char *) "w", 0);
+ PyObject *new_file = PyFile_FromFile (err, (char *) "", (char *) "w", nullptr);
sys_module_dict.SetItemForKey ("stderr", new_file);
Py_DECREF (new_file);
}
@@ -517,7 +522,7 @@ ScriptInterpreterPython::GetSysModuleDictionary ()
static std::string
GenerateUniqueName (const char* base_name_wanted,
uint32_t& functions_counter,
- void* name_token = NULL)
+ void* name_token = nullptr)
{
StreamString sstr;
@@ -538,7 +543,7 @@ ScriptInterpreterPython::GetEmbeddedInterpreterModuleObjects ()
if (!m_run_one_line_function)
{
PyObject *module = PyImport_AddModule ("lldb.embedded_interpreter");
- if (module != NULL)
+ if (module != nullptr)
{
PythonDictionary module_dict (PyModule_GetDict (module));
if (module_dict)
@@ -580,8 +585,7 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec
StreamFileSP output_file_sp;
StreamFileSP error_file_sp;
Communication output_comm ("lldb.ScriptInterpreterPython.ExecuteOneLine.comm");
- int pipe_fds[2] = { -1, -1 };
-
+ bool join_read_thread = false;
if (options.GetEnableIO())
{
if (result)
@@ -589,20 +593,21 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec
input_file_sp = debugger.GetInputFile();
// Set output to a temporary file so we can forward the results on to the result object
- int err = pipe(pipe_fds);
- if (err == 0)
+ Pipe pipe;
+ if (pipe.Open())
{
- std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe_fds[0], true));
+ std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true));
if (conn_ap->IsConnected())
{
output_comm.SetConnection(conn_ap.release());
output_comm.SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived, &result->GetOutputStream());
output_comm.StartReadThread();
- FILE *outfile_handle = fdopen (pipe_fds[1], "w");
+ join_read_thread = true;
+ FILE *outfile_handle = fdopen (pipe.ReleaseWriteFileDescriptor(), "w");
output_file_sp.reset(new StreamFile(outfile_handle, true));
error_file_sp = output_file_sp;
if (outfile_handle)
- ::setbuf (outfile_handle, NULL);
+ ::setbuf (outfile_handle, nullptr);
result->SetImmediateOutputFile(debugger.GetOutputFile()->GetFile().GetStream());
result->SetImmediateErrorFile(debugger.GetErrorFile()->GetFile().GetStream());
@@ -667,7 +672,7 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec
if (out_file != err_file)
::fflush (err_file);
- if (pipe_fds[0] != -1)
+ if (join_read_thread)
{
// Close the write end of the pipe since we are done with our
// one line script. This should cause the read thread that
@@ -788,10 +793,27 @@ public:
}
- virtual void
+ virtual bool
Interrupt ()
{
-
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+
+ PyThreadState* state = _PyThreadState_Current;
+ if (!state)
+ state = m_python->GetThreadState();
+ if (state)
+ {
+ long tid = state->thread_id;
+ _PyThreadState_Current = state;
+ int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
+ if (log)
+ log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, tid = %ld, num_threads = %d, state = %p",
+ tid, num_threads, static_cast<void *>(state));
+ }
+ else if (log)
+ log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, state = NULL");
+
+ return false;
}
virtual void
@@ -834,13 +856,13 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
{
Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN,
ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
- PyObject *py_return = NULL;
+ PyObject *py_return = nullptr;
PythonObject &main_module = GetMainModule ();
PythonDictionary globals (PyModule_GetDict(main_module.get()));
- PyObject *py_error = NULL;
+ PyObject *py_error = nullptr;
bool ret_success = false;
int success;
@@ -855,25 +877,25 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
locals = globals;
py_error = PyErr_Occurred();
- if (py_error != NULL)
+ if (py_error != nullptr)
PyErr_Clear();
- if (in_string != NULL)
+ if (in_string != nullptr)
{
{ // scope for PythonInputReaderManager
//PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
py_return = PyRun_String (in_string, Py_eval_input, globals.get(), locals.get());
- if (py_return == NULL)
+ if (py_return == nullptr)
{
py_error = PyErr_Occurred ();
- if (py_error != NULL)
+ if (py_error != nullptr)
PyErr_Clear ();
py_return = PyRun_String (in_string, Py_single_input, globals.get(), locals.get());
}
}
- if (py_return != NULL)
+ if (py_return != nullptr)
{
switch (return_type)
{
@@ -978,7 +1000,7 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
}
py_error = PyErr_Occurred();
- if (py_error != NULL)
+ if (py_error != nullptr)
{
ret_success = false;
if (options.GetMaskoutErrors())
@@ -998,14 +1020,13 @@ ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const Exec
Error error;
Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN,
ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
- bool success = false;
PythonObject return_value;
PythonObject &main_module = GetMainModule ();
PythonDictionary globals (PyModule_GetDict(main_module.get()));
- PyObject *py_error = NULL;
+ PyObject *py_error = nullptr;
PythonDictionary locals = GetSessionDictionary ();
@@ -1020,10 +1041,10 @@ ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const Exec
}
py_error = PyErr_Occurred();
- if (py_error != NULL)
+ if (py_error != nullptr)
PyErr_Clear();
- if (in_string != NULL)
+ if (in_string != nullptr)
{
struct _node *compiled_node = PyParser_SimpleParseString (in_string, Py_file_input);
if (compiled_node)
@@ -1031,27 +1052,22 @@ ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const Exec
PyCodeObject *compiled_code = PyNode_Compile (compiled_node, "temp.py");
if (compiled_code)
{
- { // scope for PythonInputReaderManager
- //PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
- return_value.Reset(PyEval_EvalCode (compiled_code, globals.get(), locals.get()));
- }
- if (return_value)
- success = true;
+ return_value.Reset(PyEval_EvalCode (compiled_code, globals.get(), locals.get()));
}
}
}
py_error = PyErr_Occurred ();
- if (py_error != NULL)
+ if (py_error != nullptr)
{
// puts(in_string);
// _PyObject_Dump (py_error);
// PyErr_Print();
// success = false;
- PyObject *type = NULL;
- PyObject *value = NULL;
- PyObject *traceback = NULL;
+ PyObject *type = nullptr;
+ PyObject *value = nullptr;
+ PyObject *traceback = nullptr;
PyErr_Fetch (&type,&value,&traceback);
// get the backtrace
@@ -1075,11 +1091,11 @@ ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const Exec
void
-ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
+ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
CommandReturnObject &result)
{
m_active_io_handler = eIOHandlerBreakpoint;
- m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, bp_options);
+ m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, &bp_options_vec);
}
void
@@ -1090,27 +1106,39 @@ ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOpti
m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, wp_options);
}
-// Set a Python one-liner as the callback for the breakpoint.
void
+ScriptInterpreterPython::SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options,
+ const char *function_name)
+{
+ // For now just cons up a oneliner that calls the provided function.
+ std::string oneliner("return ");
+ oneliner += function_name;
+ oneliner += "(frame, bp_loc, internal_dict)";
+ m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
+ oneliner.c_str());
+}
+
+// Set a Python one-liner as the callback for the breakpoint.
+Error
ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
- const char *oneliner)
+ const char *command_body_text)
{
std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
- // It's necessary to set both user_source and script_source to the oneliner.
- // The former is used to generate callback description (as in breakpoint command list)
- // while the latter is used for Python to interpret during the actual callback.
-
- data_ap->user_source.AppendString (oneliner);
- data_ap->script_source.assign (oneliner);
-
- if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source))
+ // Split the command_body_text into lines, and pass that to GenerateBreakpointCommandCallbackData. That will
+ // wrap the body in an auto-generated function, and return the function name in script_source. That is what
+ // the callback will actually invoke.
+
+ data_ap->user_source.SplitIntoLines(command_body_text);
+ Error error = GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source);
+ if (error.Success())
{
BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
+ return error;
}
-
- return;
+ else
+ return error;
}
// Set a Python one-liner as the callback for the watchpoint.
@@ -1136,24 +1164,32 @@ ScriptInterpreterPython::SetWatchpointCommandCallback (WatchpointOptions *wp_opt
return;
}
-bool
+Error
ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def)
{
// Convert StringList to one long, newline delimited, const char *.
std::string function_def_string(function_def.CopyList());
- return ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)).Success();
+ Error error = ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false));
+ return error;
}
-bool
+Error
ScriptInterpreterPython::GenerateFunction(const char *signature, const StringList &input)
{
+ Error error;
int num_lines = input.GetSize ();
if (num_lines == 0)
- return false;
+ {
+ error.SetErrorString ("No input data.");
+ return error;
+ }
if (!signature || *signature == 0)
- return false;
+ {
+ error.SetErrorString("No output function name.");
+ return error;
+ }
StreamString sstr;
StringList auto_generated_function;
@@ -1180,11 +1216,9 @@ ScriptInterpreterPython::GenerateFunction(const char *signature, const StringLis
// Verify that the results are valid Python.
- if (!ExportFunctionDefinitionToInterpreter (auto_generated_function))
- return false;
+ error = ExportFunctionDefinitionToInterpreter (auto_generated_function);
- return true;
-
+ return error;
}
bool
@@ -1204,7 +1238,7 @@ ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std
std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_type_print_func", num_created_functions, name_token));
sstr.Printf ("def %s (valobj, internal_dict):", auto_generated_function_name.c_str());
- if (!GenerateFunction(sstr.GetData(), user_input))
+ if (!GenerateFunction(sstr.GetData(), user_input).Success())
return false;
// Store the name of the auto-generated function to be called.
@@ -1227,7 +1261,7 @@ ScriptInterpreterPython::GenerateScriptAliasFunction (StringList &user_input, st
sstr.Printf ("def %s (debugger, args, result, internal_dict):", auto_generated_function_name.c_str());
- if (!GenerateFunction(sstr.GetData(),user_input))
+ if (!GenerateFunction(sstr.GetData(),user_input).Success())
return false;
// Store the name of the auto-generated function to be called.
@@ -1273,7 +1307,7 @@ ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::st
// Verify that the results are valid Python.
// (even though the method is ExportFunctionDefinitionToInterpreter, a class will actually be exported)
// (TODO: rename that method to ExportDefinitionToInterpreter)
- if (!ExportFunctionDefinitionToInterpreter (auto_generated_class))
+ if (!ExportFunctionDefinitionToInterpreter (auto_generated_class).Success())
return false;
// Store the name of the auto-generated class
@@ -1285,7 +1319,7 @@ ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::st
lldb::ScriptInterpreterObjectSP
ScriptInterpreterPython::OSPlugin_CreatePluginObject (const char *class_name, lldb::ProcessSP process_sp)
{
- if (class_name == NULL || class_name[0] == '\0')
+ if (class_name == nullptr || class_name[0] == '\0')
return lldb::ScriptInterpreterObjectSP();
if (!process_sp)
@@ -1319,7 +1353,7 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP
PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject();
- if (implementor == NULL || implementor == Py_None)
+ if (implementor == nullptr || implementor == Py_None)
return lldb::ScriptInterpreterObjectSP();
PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
@@ -1329,7 +1363,7 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP
PyErr_Clear();
}
- if (pmeth == NULL || pmeth == Py_None)
+ if (pmeth == nullptr || pmeth == Py_None)
{
Py_XDECREF(pmeth);
return lldb::ScriptInterpreterObjectSP();
@@ -1354,7 +1388,7 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP
Py_XDECREF(pmeth);
// right now we know this function exists and is callable..
- PyObject* py_return = PyObject_CallMethod(implementor, callee_name, NULL);
+ PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr);
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
@@ -1380,7 +1414,7 @@ ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP o
PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject();
- if (implementor == NULL || implementor == Py_None)
+ if (implementor == nullptr || implementor == Py_None)
return lldb::ScriptInterpreterObjectSP();
PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
@@ -1390,7 +1424,7 @@ ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP o
PyErr_Clear();
}
- if (pmeth == NULL || pmeth == Py_None)
+ if (pmeth == nullptr || pmeth == Py_None)
{
Py_XDECREF(pmeth);
return lldb::ScriptInterpreterObjectSP();
@@ -1415,7 +1449,7 @@ ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP o
Py_XDECREF(pmeth);
// right now we know this function exists and is callable..
- PyObject* py_return = PyObject_CallMethod(implementor, callee_name, NULL);
+ PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr);
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
@@ -1437,7 +1471,7 @@ template <typename T>
const char *GetPythonValueFormatString(T t)
{
assert(!"Unhandled type passed to GetPythonValueFormatString(T), make a specialization of GetPythonValueFormatString() to support this type.");
- return NULL;
+ return nullptr;
}
template <> const char *GetPythonValueFormatString (char *) { return "s"; }
template <> const char *GetPythonValueFormatString (char) { return "b"; }
@@ -1469,7 +1503,7 @@ ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterOb
PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject();
- if (implementor == NULL || implementor == Py_None)
+ if (implementor == nullptr || implementor == Py_None)
return lldb::ScriptInterpreterObjectSP();
PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
@@ -1479,7 +1513,7 @@ ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterOb
PyErr_Clear();
}
- if (pmeth == NULL || pmeth == Py_None)
+ if (pmeth == nullptr || pmeth == Py_None)
{
Py_XDECREF(pmeth);
return lldb::ScriptInterpreterObjectSP();
@@ -1535,7 +1569,7 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP
PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject();
- if (implementor == NULL || implementor == Py_None)
+ if (implementor == nullptr || implementor == Py_None)
return lldb::ScriptInterpreterObjectSP();
PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
@@ -1545,7 +1579,7 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP
PyErr_Clear();
}
- if (pmeth == NULL || pmeth == Py_None)
+ if (pmeth == nullptr || pmeth == Py_None)
{
Py_XDECREF(pmeth);
return lldb::ScriptInterpreterObjectSP();
@@ -1627,7 +1661,7 @@ lldb::ScriptInterpreterObjectSP
ScriptInterpreterPython::CreateSyntheticScriptedProvider (const char *class_name,
lldb::ValueObjectSP valobj)
{
- if (class_name == NULL || class_name[0] == '\0')
+ if (class_name == nullptr || class_name[0] == '\0')
return lldb::ScriptInterpreterObjectSP();
if (!valobj.get())
@@ -1675,25 +1709,29 @@ ScriptInterpreterPython::GenerateTypeSynthClass (const char* oneliner, std::stri
}
-bool
+Error
ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, std::string& output)
{
static uint32_t num_created_functions = 0;
user_input.RemoveBlankLines ();
StreamString sstr;
-
+ Error error;
if (user_input.GetSize() == 0)
- return false;
+ {
+ error.SetErrorString("No input data.");
+ return error;
+ }
std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_bp_callback_func_",num_created_functions));
sstr.Printf ("def %s (frame, bp_loc, internal_dict):", auto_generated_function_name.c_str());
- if (!GenerateFunction(sstr.GetData(), user_input))
- return false;
+ error = GenerateFunction(sstr.GetData(), user_input);
+ if (!error.Success())
+ return error;
// Store the name of the auto-generated function to be called.
output.assign(auto_generated_function_name);
- return true;
+ return error;
}
bool
@@ -1709,7 +1747,7 @@ ScriptInterpreterPython::GenerateWatchpointCommandCallbackData (StringList &user
std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_wp_callback_func_",num_created_functions));
sstr.Printf ("def %s (frame, wp, internal_dict):", auto_generated_function_name.c_str());
- if (!GenerateFunction(sstr.GetData(), user_input))
+ if (!GenerateFunction(sstr.GetData(), user_input).Success())
return false;
// Store the name of the auto-generated function to be called.
@@ -1732,7 +1770,7 @@ ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name,
return false;
}
- void* old_callee = (callee_wrapper_sp ? callee_wrapper_sp->GetObject() : NULL);
+ void* old_callee = (callee_wrapper_sp ? callee_wrapper_sp->GetObject() : nullptr);
void* new_callee = old_callee;
bool ret_val;
@@ -1764,6 +1802,21 @@ ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name,
}
+void
+ScriptInterpreterPython::Clear ()
+{
+ // Release any global variables that might have strong references to
+ // LLDB objects when clearing the python script interpreter.
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+
+ // This may be called as part of Py_Finalize. In that case the modules are destroyed in random
+ // order and we can't guarantee that we can access these.
+ if (Py_IsInitialized())
+ PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process = None; lldb.thread = None; lldb.frame = None");
+}
+
bool
ScriptInterpreterPython::BreakpointCallbackFunction
(
@@ -1914,10 +1967,10 @@ ScriptInterpreterPython::GetChildAtIndex (const lldb::ScriptInterpreterObjectSP&
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
void* child_ptr = g_swig_get_child_index (implementor,idx);
- if (child_ptr != NULL && child_ptr != Py_None)
+ 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 == NULL)
+ if (sb_value_ptr == nullptr)
Py_XDECREF(child_ptr);
else
ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr);
@@ -2006,15 +2059,15 @@ ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance (const lldb::Scr
static std::string
ReadPythonBacktrace (PyObject* py_backtrace)
{
- PyObject* traceback_module = NULL,
- *stringIO_module = NULL,
- *stringIO_builder = NULL,
- *stringIO_buffer = NULL,
- *printTB = NULL,
- *printTB_args = NULL,
- *printTB_result = NULL,
- *stringIO_getvalue = NULL,
- *printTB_string = NULL;
+ PyObject* traceback_module = nullptr,
+ *stringIO_module = nullptr,
+ *stringIO_builder = nullptr,
+ *stringIO_buffer = nullptr,
+ *printTB = nullptr,
+ *printTB_args = nullptr,
+ *printTB_result = nullptr,
+ *stringIO_getvalue = nullptr,
+ *printTB_string = nullptr;
std::string retval("backtrace unavailable");
@@ -2028,7 +2081,7 @@ ReadPythonBacktrace (PyObject* py_backtrace)
stringIO_builder = PyObject_GetAttrString(stringIO_module, "StringIO");
if (stringIO_builder && stringIO_builder != Py_None)
{
- stringIO_buffer = PyObject_CallObject(stringIO_builder, NULL);
+ stringIO_buffer = PyObject_CallObject(stringIO_builder, nullptr);
if (stringIO_buffer && stringIO_buffer != Py_None)
{
printTB = PyObject_GetAttrString(traceback_module, "print_tb");
@@ -2039,7 +2092,7 @@ ReadPythonBacktrace (PyObject* py_backtrace)
stringIO_getvalue = PyObject_GetAttrString(stringIO_buffer, "getvalue");
if (stringIO_getvalue && stringIO_getvalue != Py_None)
{
- printTB_string = PyObject_CallObject (stringIO_getvalue,NULL);
+ printTB_string = PyObject_CallObject (stringIO_getvalue,nullptr);
if (printTB_string && printTB_string != Py_None && PyString_Check(printTB_string))
retval.assign(PyString_AsString(printTB_string));
}
@@ -2393,29 +2446,20 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function,
{
error.SetErrorString("invalid Debugger pointer");
return false;
- }
+ }
bool ret_val = false;
std::string err_msg;
-
+
{
Locker py_lock(this,
- Locker::AcquireLock | Locker::InitSession,
+ Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
Locker::FreeLock | Locker::TearDownSession);
SynchronicityHandler synch_handler(debugger_sp,
synchronicity);
- // we need to save the thread state when we first start the command
- // because we might decide to interrupt it while some action is taking
- // place outside of Python (e.g. printing to screen, waiting for the network, ...)
- // in that case, _PyThreadState_Current will be NULL - and we would be unable
- // to set the asynchronous exception - not a desirable situation
- m_command_thread_state = _PyThreadState_Current;
-
- //PythonInputReaderManager py_input(this);
-
ret_val = g_swig_call_command (impl_function,
m_dictionary_name.c_str(),
debugger_sp,
@@ -2443,7 +2487,7 @@ ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string&
std::string command(item);
command += ".__doc__";
- char* result_ptr = NULL; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully
+ char* result_ptr = nullptr; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully
if (ExecuteOneLineWithReturn (command.c_str(),
ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
@@ -2561,7 +2605,7 @@ ScriptInterpreterPython::InitializePrivate ()
FileSpec file_spec;
char python_dir_path[PATH_MAX];
- if (Host::GetLLDBPath (ePathTypePythonDir, file_spec))
+ if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec))
{
std::string python_path("sys.path.insert(0,\"");
size_t orig_len = python_path.length();
@@ -2572,8 +2616,8 @@ ScriptInterpreterPython::InitializePrivate ()
PyRun_SimpleString (python_path.c_str());
python_path.resize (orig_len);
}
-
- if (Host::GetLLDBPath (ePathTypeLLDBShlibDir, file_spec))
+
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec))
{
if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path)))
{
@@ -2585,7 +2629,7 @@ ScriptInterpreterPython::InitializePrivate ()
}
}
- PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line; from termios import *");
+ PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line");
if (threads_already_initialized) {
if (log)
diff --git a/source/Interpreter/embedded_interpreter.py b/source/Interpreter/embedded_interpreter.py
index bc0dd6d5ae4f..51a971690d67 100644
--- a/source/Interpreter/embedded_interpreter.py
+++ b/source/Interpreter/embedded_interpreter.py
@@ -9,6 +9,10 @@ try:
import rlcompleter
except ImportError:
have_readline = False
+except AttributeError:
+ # This exception gets hit by the rlcompleter when Linux is using
+ # the readline suppression import.
+ have_readline = False
else:
have_readline = True
if 'libedit' in readline.__doc__:
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
index abf873ff3dd1..a9f8f3b668dc 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -24,6 +24,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "Utility/ARM_DWARF_Registers.h"
@@ -144,7 +145,7 @@ static RegisterInfo g_register_infos[] =
{ "r13_svc", "sp_svc", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_svc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r14_svc", "lr_svc", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_svc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}
};
-static const uint32_t k_num_register_infos = sizeof(g_register_infos)/sizeof(RegisterInfo);
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
static bool g_register_info_names_constified = false;
const lldb_private::RegisterInfo *
@@ -214,7 +215,7 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread,
llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
- for (size_t i = 0; i < (sizeof(reg_names) / sizeof(reg_names[0])); ++i)
+ for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i)
{
if (ai == ae)
break;
@@ -522,7 +523,13 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
{
DataExtractor data;
- size_t num_bytes = new_value_sp->GetData(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)
{
diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
new file mode 100644
index 000000000000..8f7962d095fc
--- /dev/null
+++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
@@ -0,0 +1,1103 @@
+//===-- ABIMacOSX_arm64.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABIMacOSX_arm64.h"
+
+#include "lldb/Core/ConstString.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/Scalar.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+
+#include "Utility/ARM64_DWARF_Registers.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+static const char *pluginDesc = "Mac OS X ABI for arm64 targets";
+static const char *pluginShort = "abi.macosx-arm64";
+
+
+static RegisterInfo g_register_infos[] =
+{
+ // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE
+ // ========== ======= == === ============= =================== =================== ====================== =========================== ======================= ======================
+ { "x0", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x1", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x2", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x3", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x4", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x5", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x6", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x7", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x8", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x9", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x10", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x11", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x12", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x13", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x14", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x15", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x16", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x17", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x18", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x19", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x20", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x21", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x22", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x23", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x24", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x25", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x26", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x27", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x28", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "fp", "x29", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x29, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "lr", "x30", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "sp", "x31", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "pc", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+
+ { "v0", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v1", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v2", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v3", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v4", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v5", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v6", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v7", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v8", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v9", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v10", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v11", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v12", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v13", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v14", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v15", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v16", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v17", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v18", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v19", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v20", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v21", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v22", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v23", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v24", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v25", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v26", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v27", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v28", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v29", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v30", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v31", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+
+ { "fpsr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "fpcr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+
+ { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+
+ { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
+};
+
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+static bool g_register_info_names_constified = false;
+
+const lldb_private::RegisterInfo *
+ABIMacOSX_arm64::GetRegisterInfoArray (uint32_t &count)
+{
+ // Make the C-string names and alt_names for the register infos into const
+ // C-string values by having the ConstString unique the names in the global
+ // constant C-string pool.
+ if (!g_register_info_names_constified)
+ {
+ g_register_info_names_constified = true;
+ for (uint32_t i=0; i<k_num_register_infos; ++i)
+ {
+ if (g_register_infos[i].name)
+ g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString();
+ if (g_register_infos[i].alt_name)
+ g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString();
+ }
+ }
+ count = k_num_register_infos;
+ return g_register_infos;
+}
+
+size_t
+ABIMacOSX_arm64::GetRedZoneSize () const
+{
+ return 128;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABIMacOSX_arm64::CreateInstance (const ArchSpec &arch)
+{
+ static ABISP g_abi_sp;
+ if (arch.GetTriple().getArch() == llvm::Triple::aarch64)
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABIMacOSX_arm64);
+ return g_abi_sp;
+ }
+ return ABISP();
+}
+
+bool
+ABIMacOSX_arm64::PrepareTrivialCall (Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t func_addr,
+ lldb::addr_t return_addr,
+ llvm::ArrayRef<lldb::addr_t> args) const
+{
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return false;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ StreamString s;
+ s.Printf("ABISysV_x86_64::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%d = 0x%" PRIx64, static_cast<int>(i + 1), args[i]);
+ s.PutCString (")");
+ log->PutCString(s.GetString().c_str());
+ }
+
+ const uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ const uint32_t ra_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+
+ // x0 - x7 contain first 8 simple args
+ if (args.size() > 8) // TODO handle more than 6 arguments
+ return false;
+
+ for (size_t i = 0; i < args.size(); ++i)
+ {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
+ if (log)
+ log->Printf("About to write arg%d (0x%" PRIx64 ") into %s",
+ static_cast<int>(i + 1), args[i], reg_info->name);
+ if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
+ return false;
+ }
+
+ // Set "lr" to the return address
+ if (!reg_ctx->WriteRegisterFromUnsigned (reg_ctx->GetRegisterInfoAtIndex (ra_reg_num), return_addr))
+ return false;
+
+ // Set "sp" to the requested value
+ if (!reg_ctx->WriteRegisterFromUnsigned (reg_ctx->GetRegisterInfoAtIndex (sp_reg_num), sp))
+ return false;
+
+ // Set "pc" to the address requested
+ if (!reg_ctx->WriteRegisterFromUnsigned (reg_ctx->GetRegisterInfoAtIndex (pc_reg_num), func_addr))
+ return false;
+
+ return true;
+}
+
+
+bool
+ABIMacOSX_arm64::GetArgumentValues (Thread &thread, ValueList &values) const
+{
+ uint32_t num_values = values.GetSize();
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+
+ // Extract the register context so we can read arguments from registers
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+
+ if (!reg_ctx)
+ return false;
+
+ addr_t sp = 0;
+
+ for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx)
+ {
+ // We currently only support extracting values with Clang QualTypes.
+ // Do we care about others?
+ Value *value = values.GetValueAtIndex(value_idx);
+
+ if (!value)
+ return false;
+
+ ClangASTType value_type = value->GetClangType();
+ if (value_type)
+ {
+ bool is_signed = false;
+ size_t bit_width = 0;
+ if (value_type.IsIntegerType (is_signed))
+ {
+ bit_width = value_type.GetBitSize();
+ }
+ else if (value_type.IsPointerOrReferenceType ())
+ {
+ bit_width = value_type.GetBitSize();
+ }
+ else
+ {
+ // We only handle integer, pointer and reference types currently...
+ return false;
+ }
+
+ if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8))
+ {
+ if (value_idx < 8)
+ {
+ // Arguments 1-6 are in x0-x5...
+ const RegisterInfo *reg_info = NULL;
+ // Search by generic ID first, then fall back to by name
+ uint32_t arg_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx);
+ if (arg_reg_num != LLDB_INVALID_REGNUM)
+ {
+ reg_info = reg_ctx->GetRegisterInfoAtIndex(arg_reg_num);
+ }
+ else
+ {
+ switch (value_idx)
+ {
+ case 0: reg_info = reg_ctx->GetRegisterInfoByName("x0"); break;
+ case 1: reg_info = reg_ctx->GetRegisterInfoByName("x1"); break;
+ case 2: reg_info = reg_ctx->GetRegisterInfoByName("x2"); break;
+ case 3: reg_info = reg_ctx->GetRegisterInfoByName("x3"); break;
+ case 4: reg_info = reg_ctx->GetRegisterInfoByName("x4"); break;
+ case 5: reg_info = reg_ctx->GetRegisterInfoByName("x5"); break;
+ case 6: reg_info = reg_ctx->GetRegisterInfoByName("x6"); break;
+ case 7: reg_info = reg_ctx->GetRegisterInfoByName("x7"); break;
+ }
+ }
+
+ if (reg_info)
+ {
+ RegisterValue reg_value;
+
+ if (reg_ctx->ReadRegister(reg_info, reg_value))
+ {
+ if (is_signed)
+ reg_value.SignExtend(bit_width);
+ if (!reg_value.GetScalarValue(value->GetScalar()))
+ return false;
+ continue;
+ }
+ }
+ return false;
+ }
+ else
+ {
+ if (sp == 0)
+ {
+ // Read the stack pointer if we already haven't read it
+ sp = reg_ctx->GetSP(0);
+ if (sp == 0)
+ return false;
+ }
+
+ // Arguments 5 on up are on the stack
+ const uint32_t arg_byte_size = (bit_width + (8-1)) / 8;
+ Error error;
+ if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory(sp, arg_byte_size, is_signed, value->GetScalar(), error))
+ return false;
+
+ sp += arg_byte_size;
+ // Align up to the next 8 byte boundary if needed
+ if (sp % 8)
+ {
+ sp >>= 3;
+ sp += 1;
+ sp <<= 3;
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+Error
+ABIMacOSX_arm64::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 return_value_type = new_value_sp->GetClangType();
+ if (!return_value_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ Thread *thread = frame_sp->GetThread().get();
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ if (reg_ctx)
+ {
+ DataExtractor data;
+ Error data_error;
+ const uint64_t byte_size = 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;
+ }
+
+ const uint32_t type_flags = return_value_type.GetTypeInfo (NULL);
+ if (type_flags & ClangASTType::eTypeIsScalar ||
+ type_flags & ClangASTType::eTypeIsPointer)
+ {
+ if (type_flags & ClangASTType::eTypeIsInteger ||
+ type_flags & ClangASTType::eTypeIsPointer )
+ {
+ // Extract the register context so we can read arguments from registers
+ lldb::offset_t offset = 0;
+ if (byte_size <= 16)
+ {
+ const RegisterInfo *x0_info = reg_ctx->GetRegisterInfoByName("x0", 0);
+ if (byte_size <= 8)
+ {
+ uint64_t raw_value = data.GetMaxU64(&offset, byte_size);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (x0_info, raw_value))
+ error.SetErrorString ("failed to write register x0");
+ }
+ else
+ {
+ uint64_t raw_value = data.GetMaxU64(&offset, 8);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (x0_info, raw_value))
+ {
+ const RegisterInfo *x1_info = reg_ctx->GetRegisterInfoByName("x1", 0);
+ raw_value = data.GetMaxU64(&offset, byte_size - offset);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (x1_info, raw_value))
+ error.SetErrorString ("failed to write register x1");
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 128 bit integer values at present.");
+ }
+ }
+ else if (type_flags & ClangASTType::eTypeIsFloat)
+ {
+ if (type_flags & ClangASTType::eTypeIsComplex)
+ {
+ // Don't handle complex yet.
+ error.SetErrorString ("returning complex float values are not supported");
+ }
+ else
+ {
+ const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);
+
+ if (v0_info)
+ {
+ if (byte_size <= 16)
+ {
+ if (byte_size <= RegisterValue::GetMaxByteSize())
+ {
+ RegisterValue reg_value;
+ error = reg_value.SetValueFromData (v0_info, data, 0, true);
+ if (error.Success())
+ {
+ if (!reg_ctx->WriteRegister (v0_info, reg_value))
+ error.SetErrorString ("failed to write register v0");
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("returning float values with a byte size of %" PRIu64 " are not supported", byte_size);
+ }
+ }
+ else
+ {
+ error.SetErrorString("returning float values longer than 128 bits are not supported");
+ }
+ }
+ else
+ {
+ error.SetErrorString("v0 register is not available on this target");
+ }
+ }
+ }
+ }
+ else if (type_flags & ClangASTType::eTypeIsVector)
+ {
+ if (byte_size > 0)
+ {
+ const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);
+
+ if (v0_info)
+ {
+ if (byte_size <= v0_info->byte_size)
+ {
+ RegisterValue reg_value;
+ error = reg_value.SetValueFromData (v0_info, data, 0, true);
+ if (error.Success())
+ {
+ if (!reg_ctx->WriteRegister (v0_info, reg_value))
+ error.SetErrorString ("failed to write register v0");
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("no registers are available");
+ }
+
+ return error;
+}
+
+bool
+ABIMacOSX_arm64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t lr_reg_num = arm64_dwarf::lr;
+ uint32_t sp_reg_num = arm64_dwarf::sp;
+ uint32_t pc_reg_num = arm64_dwarf::pc;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our previous Call Frame Address is the stack pointer
+ row->SetCFARegister (sp_reg_num);
+
+ // Our 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 ("arm64 at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+
+ return true;
+}
+
+bool
+ABIMacOSX_arm64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t fp_reg_num = arm64_dwarf::fp;
+ uint32_t pc_reg_num = arm64_dwarf::pc;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+ const int32_t ptr_size = 8;
+
+ row->SetCFARegister (fp_reg_num);
+ row->SetCFAOffset (2 * ptr_size);
+ row->SetOffset (0);
+
+ row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("arm64-apple-darwin default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+ return true;
+}
+
+// AAPCS64 (Procedure Call Standard for the ARM 64-bit Architecture) says
+// registers x19 through x28 and sp are callee preserved.
+// v8-v15 are non-volatile (and specifically only the lower 8 bytes of these regs),
+// the rest of the fp/SIMD registers are volatile.
+
+// We treat x29 as callee preserved also, else the unwinder won't try to
+// retrieve fp saves.
+
+bool
+ABIMacOSX_arm64::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+ if (reg_info)
+ {
+ const char *name = reg_info->name;
+
+ // Sometimes we'll be called with the "alternate" name for these registers;
+ // recognize them as non-volatile.
+
+ if (name[0] == 'p' && name[1] == 'c') // pc
+ return false;
+ if (name[0] == 'f' && name[1] == 'p') // fp
+ return false;
+ if (name[0] == 's' && name[1] == 'p') // sp
+ return false;
+ if (name[0] == 'l' && name[1] == 'r') // lr
+ return false;
+
+ if (name[0] == 'x')
+ {
+ // Volatile registers: x0-x18, x30 (lr)
+ // Return false for the non-volatile gpr regs, true for everything else
+ switch (name[1])
+ {
+ case '1':
+ switch (name[2])
+ {
+ case '9':
+ return false; // x19 is non-volatile
+ default:
+ return true;
+ }
+ break;
+ case '2':
+ switch (name[2])
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ return false; // x20 - 28 are non-volatile
+ case '9':
+ return false; // x29 aka fp treat as non-volatile on Darwin
+ default:
+ return true;
+ }
+ case '3': // x30 aka lr treat as non-volatile
+ if (name[2] == '0')
+ return false;
+ default:
+ return true;
+ }
+ }
+ else if (name[0] == 'v' || name[0] == 's' || name[0] == 'd')
+ {
+ // Volatile registers: v0-7, v16-v31
+ // Return false for non-volatile fp/SIMD regs, true for everything else
+ switch (name[1])
+ {
+ case '8':
+ case '9':
+ return false; // v8-v9 are non-volatile
+ case '1':
+ switch (name[2])
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ return false; // v10-v15 are non-volatile
+ default:
+ return true;
+ }
+ default:
+ return true;
+ }
+ }
+ }
+ return true;
+}
+
+static bool
+LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
+ RegisterContext *reg_ctx,
+ const ClangASTType &value_type,
+ bool is_return_value, // false => parameter, true => return value
+ uint32_t &NGRN, // NGRN (see ABI documentation)
+ uint32_t &NSRN, // NSRN (see ABI documentation)
+ DataExtractor &data)
+{
+ const size_t byte_size = value_type.GetByteSize();
+
+ if (byte_size == 0)
+ return false;
+
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
+ Error error;
+
+ ClangASTType base_type;
+ const uint32_t homogeneous_count = value_type.IsHomogeneousAggregate (&base_type);
+ if (homogeneous_count > 0 && homogeneous_count <= 8)
+ {
+ printf ("ClangASTContext::IsHomogeneousAggregate() => %u\n", homogeneous_count);
+ // Make sure we have enough registers
+ if (NSRN < 8 && (8-NSRN) >= homogeneous_count)
+ {
+ if (!base_type)
+ return false;
+ const size_t base_byte_size = base_type.GetByteSize();
+ printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size);
+ uint32_t data_offset = 0;
+
+ for (uint32_t i=0; i<homogeneous_count; ++i)
+ {
+ char v_name[8];
+ ::snprintf (v_name, sizeof(v_name), "v%u", NSRN);
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(v_name, 0);
+ if (reg_info == NULL)
+ return false;
+
+ if (base_byte_size > reg_info->byte_size)
+ return false;
+
+ RegisterValue reg_value;
+
+ if (!reg_ctx->ReadRegister(reg_info, reg_value))
+ return false;
+
+ // Make sure we have enough room in "heap_data_ap"
+ if ((data_offset + base_byte_size) <= heap_data_ap->GetByteSize())
+ {
+ const size_t bytes_copied = reg_value.GetAsMemoryData (reg_info,
+ heap_data_ap->GetBytes()+data_offset,
+ base_byte_size,
+ byte_order,
+ error);
+ if (bytes_copied != base_byte_size)
+ return false;
+ data_offset += bytes_copied;
+ ++NSRN;
+ }
+ else
+ return false;
+ }
+ data.SetByteOrder(byte_order);
+ data.SetAddressByteSize(exe_ctx.GetProcessRef().GetAddressByteSize());
+ data.SetData(DataBufferSP (heap_data_ap.release()));
+ return true;
+ }
+ }
+
+ const size_t max_reg_byte_size = 16;
+ if (byte_size <= max_reg_byte_size)
+ {
+ size_t bytes_left = byte_size;
+ uint32_t data_offset = 0;
+ while (data_offset < byte_size)
+ {
+ if (NGRN >= 8)
+ return false;
+
+ uint32_t reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + NGRN);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ return false;
+
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
+ if (reg_info == NULL)
+ return false;
+
+ RegisterValue reg_value;
+
+ if (!reg_ctx->ReadRegister(reg_info, reg_value))
+ return false;
+
+ const size_t curr_byte_size = std::min<size_t>(8,bytes_left);
+ const size_t bytes_copied = reg_value.GetAsMemoryData (reg_info, heap_data_ap->GetBytes()+data_offset, curr_byte_size, byte_order, error);
+ if (bytes_copied == 0)
+ return false;
+ if (bytes_copied >= bytes_left)
+ break;
+ data_offset += bytes_copied;
+ bytes_left -= bytes_copied;
+ ++NGRN;
+ }
+ }
+ else
+ {
+ const RegisterInfo *reg_info = NULL;
+ if (is_return_value)
+ {
+ // We are assuming we are decoding this immediately after returning
+ // from a function call and that the address of the structure is in x8
+ reg_info = reg_ctx->GetRegisterInfoByName("x8", 0);
+ }
+ else
+ {
+ // We are assuming we are stopped at the first instruction in a function
+ // and that the ABI is being respected so all parameters appear where they
+ // should be (functions with no external linkage can legally violate the ABI).
+ if (NGRN >= 8)
+ return false;
+
+ uint32_t reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + NGRN);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ return false;
+ reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
+ if (reg_info == NULL)
+ return false;
+ ++NGRN;
+ }
+
+ if (reg_info == NULL)
+ return false;
+
+ const lldb::addr_t value_addr = reg_ctx->ReadRegisterAsUnsigned(reg_info, LLDB_INVALID_ADDRESS);
+
+ if (value_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ if (exe_ctx.GetProcessRef().ReadMemory (value_addr,
+ heap_data_ap->GetBytes(),
+ heap_data_ap->GetByteSize(),
+ error) != heap_data_ap->GetByteSize())
+ {
+ return false;
+ }
+ }
+
+ data.SetByteOrder(byte_order);
+ data.SetAddressByteSize(exe_ctx.GetProcessRef().GetAddressByteSize());
+ data.SetData(DataBufferSP (heap_data_ap.release()));
+ return true;
+}
+
+ValueObjectSP
+ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+ Value value;
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
+ return return_valobj_sp;
+
+ //value.SetContext (Value::eContextTypeClangType, return_clang_type);
+ value.SetClangType(return_clang_type);
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return return_valobj_sp;
+
+ 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)
+ {
+ value.SetValueType(Value::eValueTypeScalar);
+
+ bool success = false;
+ if (type_flags & ClangASTType::eTypeIsInteger ||
+ type_flags & ClangASTType::eTypeIsPointer )
+ {
+ // Extract the register context so we can read arguments from registers
+ if (byte_size <= 8)
+ {
+ const RegisterInfo *x0_reg_info = reg_ctx->GetRegisterInfoByName("x0", 0);
+ if (x0_reg_info)
+ {
+ uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(x0_reg_info, 0);
+ const bool is_signed = (type_flags & ClangASTType::eTypeIsSigned) != 0;
+ switch (byte_size)
+ {
+ default:
+ break;
+ case 16: // uint128_t
+ // In register x0 and x1
+ {
+ const RegisterInfo *x1_reg_info = reg_ctx->GetRegisterInfoByName("x1", 0);
+
+ if (x1_reg_info)
+ {
+ if (byte_size <= x0_reg_info->byte_size + x1_reg_info->byte_size)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
+ RegisterValue x0_reg_value;
+ RegisterValue x1_reg_value;
+ if (reg_ctx->ReadRegister(x0_reg_info, x0_reg_value) &&
+ reg_ctx->ReadRegister(x1_reg_info, x1_reg_value))
+ {
+ Error error;
+ if (x0_reg_value.GetAsMemoryData (x0_reg_info, heap_data_ap->GetBytes()+0, 8, byte_order, error) &&
+ x1_reg_value.GetAsMemoryData (x1_reg_info, heap_data_ap->GetBytes()+8, 8, byte_order, error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ exe_ctx.GetProcessRef().GetAddressByteSize());
+
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ data);
+ return return_valobj_sp;
+ }
+ }
+ }
+ }
+ }
+ 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 & ClangASTType::eTypeIsFloat)
+ {
+ if (type_flags & ClangASTType::eTypeIsComplex)
+ {
+ // Don't handle complex yet.
+ }
+ else
+ {
+ if (byte_size <= sizeof(long double))
+ {
+ const RegisterInfo *v0_reg_info = reg_ctx->GetRegisterInfoByName("v0", 0);
+ RegisterValue v0_value;
+ if (reg_ctx->ReadRegister (v0_reg_info, v0_value))
+ {
+ DataExtractor data;
+ if (v0_value.GetData(data))
+ {
+ lldb::offset_t offset = 0;
+ if (byte_size == sizeof(float))
+ {
+ value.GetScalar() = data.GetFloat(&offset);
+ success = true;
+ }
+ else if (byte_size == sizeof(double))
+ {
+ value.GetScalar() = data.GetDouble(&offset);
+ success = true;
+ }
+ else if (byte_size == sizeof(long double))
+ {
+ value.GetScalar() = data.GetLongDouble(&offset);
+ success = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (success)
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+
+ }
+ else if (type_flags & ClangASTType::eTypeIsVector)
+ {
+ if (byte_size > 0)
+ {
+
+ const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);
+
+ if (v0_info)
+ {
+ if (byte_size <= v0_info->byte_size)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
+ RegisterValue reg_value;
+ if (reg_ctx->ReadRegister(v0_info, reg_value))
+ {
+ Error error;
+ if (reg_value.GetAsMemoryData (v0_info,
+ heap_data_ap->GetBytes(),
+ heap_data_ap->GetByteSize(),
+ byte_order,
+ error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ exe_ctx.GetProcessRef().GetAddressByteSize());
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ data);
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (type_flags & ClangASTType::eTypeIsStructUnion ||
+ type_flags & ClangASTType::eTypeIsClass)
+ {
+ DataExtractor data;
+
+ uint32_t NGRN = 0; // Search ABI docs for NGRN
+ uint32_t NSRN = 0; // Search ABI docs for NSRN
+ const bool is_return_value = true;
+ if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_clang_type, is_return_value, NGRN, NSRN, data))
+ {
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ data);
+ }
+ }
+ return return_valobj_sp;
+}
+
+void
+ABIMacOSX_arm64::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ pluginDesc,
+ CreateInstance);
+}
+
+void
+ABIMacOSX_arm64::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+ConstString
+ABIMacOSX_arm64::GetPluginNameStatic()
+{
+ static ConstString g_plugin_name("ABIMacOSX_arm64");
+ return g_plugin_name;
+}
+
+const char *
+ABIMacOSX_arm64::GetShortPluginName()
+{
+ return pluginShort;
+}
+
+uint32_t
+ABIMacOSX_arm64::GetPluginVersion()
+{
+ return 1;
+}
+
diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
new file mode 100644
index 000000000000..0753b23ce2a2
--- /dev/null
+++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
@@ -0,0 +1,145 @@
+//===-- ABIMacOSX_arm64.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_ABIMacOSX_arm64_h_
+#define liblldb_ABIMacOSX_arm64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Target/ABI.h"
+
+class ABIMacOSX_arm64 :
+ public lldb_private::ABI
+{
+public:
+ ~ABIMacOSX_arm64() { }
+
+ 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<lldb::addr_t> args) const;
+
+ virtual bool
+ GetArgumentValues (lldb_private::Thread &thread,
+ lldb_private::ValueList &values) 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 ()
+ {
+ // 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
+ // 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 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)
+ {
+ if (pc & (4ull - 1ull))
+ return false; // Not 4 byte aligned
+
+ // Anything else if fair game..
+ return true;
+ }
+
+ virtual bool
+ FunctionCallsChangeCFA ()
+ {
+ return false;
+ }
+
+ 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);
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ virtual lldb_private::ConstString
+ GetPluginName()
+ {
+ return GetPluginNameStatic();
+ }
+
+ virtual const char *
+ GetShortPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+ virtual lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+
+protected:
+ virtual lldb::ValueObjectSP
+ GetReturnValueObjectImpl (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &ast_type) const;
+
+private:
+ ABIMacOSX_arm64() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
+};
+
+#endif // liblldb_ABI_h_
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index 8596381b3cbc..9a1ea11cbae7 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -199,7 +199,7 @@ static RegisterInfo g_register_infos[] =
{ "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, NULL, NULL}
};
-static const uint32_t k_num_register_infos = sizeof(g_register_infos)/sizeof(RegisterInfo);
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
static bool g_register_info_names_constified = false;
const lldb_private::RegisterInfo *
@@ -600,7 +600,13 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
{
DataExtractor data;
- size_t num_bytes = new_value_sp->GetData(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)
{
diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
new file mode 100644
index 000000000000..0f01c568ed3e
--- /dev/null
+++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
@@ -0,0 +1,554 @@
+//===-- ABISysV_hexagon.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_hexagon.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/Triple.h"
+
+#include "llvm/IR/Type.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static RegisterInfo g_register_infos[] =
+{
+ // hexagon-core.xml
+ { "r00" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 0, 0, LLDB_INVALID_REGNUM, 0, 0 }, NULL, NULL },
+ { "r01" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 1, 1, LLDB_INVALID_REGNUM, 1, 1 }, NULL, NULL },
+ { "r02" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 2, 2, LLDB_INVALID_REGNUM, 2, 2 }, NULL, NULL },
+ { "r03" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 3, 3, LLDB_INVALID_REGNUM, 3, 3 }, NULL, NULL },
+ { "r04" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 4, 4, LLDB_INVALID_REGNUM, 4, 4 }, NULL, NULL },
+ { "r05" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 5, 5, LLDB_INVALID_REGNUM, 5, 5 }, NULL, NULL },
+ { "r06" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 6, 6, LLDB_INVALID_REGNUM, 6, 6 }, NULL, NULL },
+ { "r07" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 7, 7, LLDB_INVALID_REGNUM, 7, 7 }, NULL, NULL },
+ { "r08" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 8, 8, LLDB_INVALID_REGNUM, 8, 8 }, NULL, NULL },
+ { "r09" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 9, 9, LLDB_INVALID_REGNUM, 9, 9 }, NULL, NULL },
+ { "r10" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 10, 10, LLDB_INVALID_REGNUM, 10, 10 }, NULL, NULL },
+ { "r11" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 11, 11, LLDB_INVALID_REGNUM, 11, 11 }, NULL, NULL },
+ { "r12" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 12, 12, LLDB_INVALID_REGNUM, 12, 12 }, NULL, NULL },
+ { "r13" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 13, 13, LLDB_INVALID_REGNUM, 13, 13 }, NULL, NULL },
+ { "r14" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 14, 14, LLDB_INVALID_REGNUM, 14, 14 }, NULL, NULL },
+ { "r15" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 15, 15, LLDB_INVALID_REGNUM, 15, 15 }, NULL, NULL },
+ { "r16" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 16, 16, LLDB_INVALID_REGNUM, 16, 16 }, NULL, NULL },
+ { "r17" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 17, 17, LLDB_INVALID_REGNUM, 17, 17 }, NULL, NULL },
+ { "r18" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 18, 18, LLDB_INVALID_REGNUM, 18, 18 }, NULL, NULL },
+ { "r19" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 19, 19, LLDB_INVALID_REGNUM, 19, 19 }, NULL, NULL },
+ { "r20" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 20, 20, LLDB_INVALID_REGNUM, 20, 20 }, NULL, NULL },
+ { "r21" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 21, 21, LLDB_INVALID_REGNUM, 21, 21 }, NULL, NULL },
+ { "r22" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 22, 22, LLDB_INVALID_REGNUM, 22, 22 }, NULL, NULL },
+ { "r23" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 23, 23, LLDB_INVALID_REGNUM, 23, 23 }, NULL, NULL },
+ { "r24" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 24, 24, LLDB_INVALID_REGNUM, 24, 24 }, NULL, NULL },
+ { "r25" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 25, 25, LLDB_INVALID_REGNUM, 25, 25 }, NULL, NULL },
+ { "r26" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 26, 26, LLDB_INVALID_REGNUM, 26, 26 }, NULL, NULL },
+ { "r27" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 27, 27, LLDB_INVALID_REGNUM, 27, 27 }, NULL, NULL },
+ { "r28" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 28, 28, LLDB_INVALID_REGNUM, 28, 28 }, NULL, NULL },
+ { "sp" ,"r29", 4, 0, eEncodingUint, eFormatAddressInfo, { 29, 29, LLDB_REGNUM_GENERIC_SP, 29, 29 }, NULL, NULL },
+ { "fp" ,"r30", 4, 0, eEncodingUint, eFormatAddressInfo, { 30, 30, LLDB_REGNUM_GENERIC_FP, 30, 30 }, NULL, NULL },
+ { "lr" ,"r31", 4, 0, eEncodingUint, eFormatAddressInfo, { 31, 31, LLDB_REGNUM_GENERIC_RA, 31, 31 }, NULL, NULL },
+ { "sa0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 32, 32, LLDB_INVALID_REGNUM, 32, 32 }, NULL, NULL },
+ { "lc0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 33, 33, LLDB_INVALID_REGNUM, 33, 33 }, NULL, NULL },
+ { "sa1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 34, 34, LLDB_INVALID_REGNUM, 34, 34 }, NULL, NULL },
+ { "lc1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 35, 35, LLDB_INVALID_REGNUM, 35, 35 }, NULL, NULL },
+ // --> hexagon-v4/5/55/56-sim.xml
+ { "p3_0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 36, 36, LLDB_INVALID_REGNUM, 36, 36 }, NULL, NULL },
+// PADDING {
+ { "p00" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 37, 37, LLDB_INVALID_REGNUM, 37, 37 }, NULL, NULL },
+// }
+ { "m0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 38, 38, LLDB_INVALID_REGNUM, 38, 38 }, NULL, NULL },
+ { "m1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 39, 39, LLDB_INVALID_REGNUM, 39, 39 }, NULL, NULL },
+ { "usr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 40, 40, LLDB_INVALID_REGNUM, 40, 40 }, NULL, NULL },
+ { "pc" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 41, 41, LLDB_REGNUM_GENERIC_PC, 41, 41 }, NULL, NULL },
+ { "ugp" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 42, 42, LLDB_INVALID_REGNUM, 42, 42 }, NULL, NULL },
+ { "gp" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 43, 43, LLDB_INVALID_REGNUM, 43, 43 }, NULL, NULL },
+ { "cs0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 44, 44, LLDB_INVALID_REGNUM, 44, 44 }, NULL, NULL },
+ { "cs1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 45, 45, LLDB_INVALID_REGNUM, 45, 45 }, NULL, NULL },
+// PADDING {
+ { "p01" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 46, 46, LLDB_INVALID_REGNUM, 46, 46 }, NULL, NULL },
+ { "p02" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 47, 47, LLDB_INVALID_REGNUM, 47, 47 }, NULL, NULL },
+ { "p03" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 48, 48, LLDB_INVALID_REGNUM, 48, 48 }, NULL, NULL },
+ { "p04" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 49, 49, LLDB_INVALID_REGNUM, 49, 49 }, NULL, NULL },
+ { "p05" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 50, 50, LLDB_INVALID_REGNUM, 50, 50 }, NULL, NULL },
+ { "p06" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 51, 51, LLDB_INVALID_REGNUM, 51, 51 }, NULL, NULL },
+ { "p07" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 52, 52, LLDB_INVALID_REGNUM, 52, 52 }, NULL, NULL },
+ { "p08" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 53, 53, LLDB_INVALID_REGNUM, 53, 53 }, NULL, NULL },
+ { "p09" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 54, 54, LLDB_INVALID_REGNUM, 54, 54 }, NULL, NULL },
+ { "p10" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 55, 55, LLDB_INVALID_REGNUM, 55, 55 }, NULL, NULL },
+ { "p11" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 56, 56, LLDB_INVALID_REGNUM, 56, 56 }, NULL, NULL },
+ { "p12" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 57, 57, LLDB_INVALID_REGNUM, 57, 57 }, NULL, NULL },
+ { "p13" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 58, 58, LLDB_INVALID_REGNUM, 58, 58 }, NULL, NULL },
+ { "p14" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 59, 59, LLDB_INVALID_REGNUM, 59, 59 }, NULL, NULL },
+ { "p15" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 60, 60, LLDB_INVALID_REGNUM, 60, 60 }, NULL, NULL },
+ { "p16" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 61, 61, LLDB_INVALID_REGNUM, 61, 61 }, NULL, NULL },
+ { "p17" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 62, 62, LLDB_INVALID_REGNUM, 62, 62 }, NULL, NULL },
+ { "p18" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 63, 63, LLDB_INVALID_REGNUM, 63, 63 }, NULL, NULL },
+// }
+ { "sgp0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 64, 64, LLDB_INVALID_REGNUM, 64, 64 }, NULL, NULL },
+// PADDING {
+ { "p19" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 65, 65, LLDB_INVALID_REGNUM, 65, 65 }, NULL, NULL },
+// }
+ { "stid" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 66, 66, LLDB_INVALID_REGNUM, 66, 66 }, NULL, NULL },
+ { "elr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 67, 67, LLDB_INVALID_REGNUM, 67, 67 }, NULL, NULL },
+ { "badva0", "", 4, 0, eEncodingUint, eFormatAddressInfo, { 68, 68, LLDB_INVALID_REGNUM, 68, 68 }, NULL, NULL },
+ { "badva1", "", 4, 0, eEncodingUint, eFormatAddressInfo, { 69, 69, LLDB_INVALID_REGNUM, 69, 69 }, NULL, NULL },
+ { "ssr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 70, 70, LLDB_INVALID_REGNUM, 70, 70 }, NULL, NULL },
+ { "ccr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 71, 71, LLDB_INVALID_REGNUM, 71, 71 }, NULL, NULL },
+ { "htid" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 72, 72, LLDB_INVALID_REGNUM, 72, 72 }, NULL, NULL },
+// PADDING {
+ { "p20" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 73, 73, LLDB_INVALID_REGNUM, 73, 73 }, NULL, NULL },
+// }
+ { "imask" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 74, 74, LLDB_INVALID_REGNUM, 74, 74 }, NULL, NULL },
+// PADDING {
+ { "p21" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 75, 75, LLDB_INVALID_REGNUM, 75, 75 }, NULL, NULL },
+ { "p22" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 76, 76, LLDB_INVALID_REGNUM, 76, 76 }, NULL, NULL },
+ { "p23" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 77, 77, LLDB_INVALID_REGNUM, 77, 77 }, NULL, NULL },
+ { "p24" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 78, 78, LLDB_INVALID_REGNUM, 78, 78 }, NULL, NULL },
+ { "p25" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 79, 79, LLDB_INVALID_REGNUM, 79, 79 }, NULL, NULL },
+ // }
+ { "g0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 80, 80, LLDB_INVALID_REGNUM, 80, 80 }, NULL, NULL },
+ { "g1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 81, 81, LLDB_INVALID_REGNUM, 81, 81 }, NULL, NULL },
+ { "g2" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 82, 82, LLDB_INVALID_REGNUM, 82, 82 }, NULL, NULL },
+ { "g3" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 83, 83, LLDB_INVALID_REGNUM, 83, 83 }, NULL, NULL }
+};
+
+static const uint32_t k_num_register_infos = sizeof(g_register_infos)/sizeof(RegisterInfo);
+static bool g_register_info_names_constified = false;
+
+const lldb_private::RegisterInfo *
+ABISysV_hexagon::GetRegisterInfoArray ( uint32_t &count )
+{
+ // Make the C-string names and alt_names for the register infos into const
+ // C-string values by having the ConstString unique the names in the global
+ // constant C-string pool.
+ if (!g_register_info_names_constified)
+ {
+ g_register_info_names_constified = true;
+ for (uint32_t i=0; i<k_num_register_infos; ++i)
+ {
+ if (g_register_infos[i].name)
+ g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString();
+ if (g_register_infos[i].alt_name)
+ g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString();
+ }
+ }
+ count = k_num_register_infos;
+ return g_register_infos;
+}
+
+/*
+ http://en.wikipedia.org/wiki/Red_zone_%28computing%29
+
+ In computing, a red zone is a fixed size area in memory beyond the stack pointer that has not been
+ "allocated". This region of memory is not to be modified by interrupt/exception/signal handlers.
+ This allows the space to be used for temporary data without the extra overhead of modifying the
+ stack pointer. The x86-64 ABI mandates a 128 byte red zone.[1] The OpenRISC toolchain assumes a
+ 128 byte red zone though it is not documented.
+*/
+size_t
+ABISysV_hexagon::GetRedZoneSize () const
+{
+ return 0;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABISysV_hexagon::CreateInstance ( const ArchSpec &arch )
+{
+ static ABISP g_abi_sp;
+ if (arch.GetTriple().getArch() == llvm::Triple::hexagon)
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABISysV_hexagon);
+ return g_abi_sp;
+ }
+ return ABISP();
+}
+
+bool
+ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
+ lldb::addr_t sp ,
+ lldb::addr_t pc ,
+ lldb::addr_t ra ,
+ llvm::ArrayRef<addr_t> args ) const
+{
+ // we don't use the traditional trivial call specialized for jit
+ return false;
+}
+
+/*
+
+// AD:
+// . safeguard the current stack
+// . how can we know that the called function will create its own frame properly?
+// . we could manually make a new stack first:
+// 2. push RA
+// 3. push FP
+// 4. FP = SP
+// 5. SP = SP ( since no locals in our temp frame )
+
+// AD 6/05/2014
+// . variable argument list parameters are not passed via registers, they are passed on
+// the stack. This presents us with a problem, since we need to know when the valist
+// starts. Currently I can find out if a function is varg, but not how many
+// real parameters it takes. Thus I don't know when to start spilling the vargs. For
+// the time being, to progress, I will assume that it takes on real parameter before
+// the vargs list starts.
+
+// AD 06/05/2014
+// . how do we adhere to the stack alignment requirements
+
+// AD 06/05/2014
+// . handle 64bit values and their register / stack requirements
+
+*/
+#define HEX_ABI_DEBUG 1
+bool
+ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
+ lldb::addr_t sp ,
+ lldb::addr_t pc ,
+ lldb::addr_t ra ,
+ llvm::Type &prototype,
+ llvm::ArrayRef<ABI::CallArgument> args) const
+{
+ // default number of register passed arguments for varg functions
+ const int nVArgRegParams = 1;
+ Error error;
+
+ // grab the process so we have access to the memory for spilling
+ lldb::ProcessSP proc = thread.GetProcess( );
+
+ // push host data onto target
+ for ( size_t i = 0; i < args.size( ); i++ )
+ {
+ const ABI::CallArgument &arg = args[i];
+ // skip over target values
+ if ( arg.type == ABI::CallArgument::TargetValue )
+ continue;
+ // round up to 8 byte multiple
+ size_t argSize = ( arg.size | 0x7 ) + 1;
+
+ // create space on the stack for this data
+ sp -= argSize;
+
+ // write this argument onto the stack of the host process
+ proc.get( )->WriteMemory( sp, arg.data, arg.size, error );
+ if ( error.Fail( ) )
+ return false;
+
+ // update the argument with the target pointer
+ //XXX: This is a gross hack for getting around the const
+ *((size_t*)(&arg.value)) = sp;
+ }
+
+
+#if HEX_ABI_DEBUG
+ // print the original stack pointer
+ printf( "sp : %04lx \n", sp );
+#endif
+
+ // make sure number of parameters matches prototype
+ assert( prototype.getFunctionNumParams( ) == args.size( ) );
+
+ // check if this is a variable argument function
+ bool isVArg = prototype.isFunctionVarArg();
+
+ // get the register context for modifying all of the registers
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return false;
+
+ // number of arguments passed by register
+ int nRegArgs = nVArgRegParams;
+ if (! isVArg )
+ {
+ // number of arguments is limited by [R0 : R5] space
+ nRegArgs = args.size( );
+ if ( nRegArgs > 6 )
+ nRegArgs = 6;
+ }
+
+ // pass arguments that are passed via registers
+ for ( int i = 0; i < nRegArgs; i++ )
+ {
+ // get the parameter as a u32
+ uint32_t param = (uint32_t)args[i].value;
+ // write argument into register
+ if (!reg_ctx->WriteRegisterFromUnsigned( i, param ))
+ return false;
+ }
+
+ // number of arguments to spill onto stack
+ int nSpillArgs = args.size( ) - nRegArgs;
+ // make space on the stack for arguments
+ sp -= 4 * nSpillArgs;
+ // align stack on an 8 byte boundary
+ if ( sp & 7 )
+ sp -= 4;
+
+ // arguments that are passed on the stack
+ for ( size_t i = nRegArgs, offs=0; i < args.size( ); i++ )
+ {
+ // get the parameter as a u32
+ uint32_t param = (uint32_t)args[i].value;
+ // write argument to stack
+ proc->WriteMemory( sp + offs, (void*)&param, sizeof( param ), error );
+ if ( !error.Success( ) )
+ return false;
+ //
+ offs += 4;
+ }
+
+ // update registers with current function call state
+ reg_ctx->WriteRegisterFromUnsigned ( 41, pc );
+ reg_ctx->WriteRegisterFromUnsigned ( 31, ra );
+ reg_ctx->WriteRegisterFromUnsigned ( 29, sp );
+// reg_ctx->WriteRegisterFromUnsigned ( FP ??? );
+
+#if HEX_ABI_DEBUG
+ // quick and dirty stack dumper for debugging
+ for ( int i = -8; i < 8; i++ )
+ {
+ uint32_t data = 0;
+ lldb::addr_t addr = sp + i * 4;
+ proc->ReadMemory( addr, (void*)&data, sizeof( data ), error );
+ printf( "\n0x%04lx 0x%08x ", addr, data );
+ if ( i == 0 ) printf( "<<-- sp" );
+ }
+ printf( "\n" );
+#endif
+
+ return true;
+}
+
+bool
+ABISysV_hexagon::GetArgumentValues ( Thread &thread, ValueList &values ) const
+{
+ return false;
+}
+
+Error
+ABISysV_hexagon::SetReturnValueObject ( lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp )
+{
+ Error error;
+ return error;
+}
+
+ValueObjectSP
+ABISysV_hexagon::GetReturnValueObjectSimple ( Thread &thread, ClangASTType &return_clang_type ) const
+{
+ ValueObjectSP return_valobj_sp;
+ return return_valobj_sp;
+}
+
+ValueObjectSP
+ABISysV_hexagon::GetReturnValueObjectImpl ( Thread &thread, ClangASTType &return_clang_type ) const
+{
+ ValueObjectSP return_valobj_sp;
+ return return_valobj_sp;
+}
+
+// called when we are on the first instruction of a new function
+// for hexagon the return address is in RA (R31)
+bool
+ABISysV_hexagon::CreateFunctionEntryUnwindPlan ( UnwindPlan &unwind_plan )
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind(eRegisterKindGeneric);
+ unwind_plan.SetReturnAddressRegister(LLDB_REGNUM_GENERIC_RA);
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our Call Frame Address is the stack pointer value
+ row->SetCFARegister(LLDB_REGNUM_GENERIC_SP);
+ row->SetCFAOffset(4);
+ row->SetOffset(0);
+
+ // The previous PC is in the LR
+ row->SetRegisterLocationToRegister(LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_RA, true);
+ unwind_plan.AppendRow(row);
+
+ unwind_plan.SetSourceName("hexagon at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
+ return true;
+}
+
+bool
+ABISysV_hexagon::CreateDefaultUnwindPlan ( UnwindPlan &unwind_plan )
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind(eRegisterKindGeneric);
+
+ uint32_t fp_reg_num = LLDB_REGNUM_GENERIC_FP;
+ uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP;
+ uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ row->SetCFARegister(LLDB_REGNUM_GENERIC_FP);
+ row->SetCFAOffset(8);
+
+ row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num,-8, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num,-4, true);
+ row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
+
+ unwind_plan.AppendRow(row);
+ unwind_plan.SetSourceName("hexagon default unwind plan");
+ unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
+ return true;
+}
+
+/*
+ Register Usage Saved By
+
+ R0 - R5 parameters(a) -
+ R6 - R15 Scratch(b) Caller
+ R16 - R27 Scratch Callee
+ R28 Scratch(b) Caller
+ R29 - R31 Stack Frames Callee(c)
+ P3:0 Processor State Caller
+
+ a = the caller can change parameter values
+ b = R14 - R15 and R28 are used by the procedure linkage table
+ c = R29 - R31 are saved and restored by allocframe() and deallocframe()
+*/
+bool
+ABISysV_hexagon::RegisterIsVolatile ( const RegisterInfo *reg_info )
+{
+ return !RegisterIsCalleeSaved( reg_info );
+}
+
+bool
+ABISysV_hexagon::RegisterIsCalleeSaved ( const RegisterInfo *reg_info )
+{
+ int reg = ((reg_info->byte_offset) / 4);
+
+ bool save = (reg >= 16) && (reg <= 27);
+ save |= (reg >= 29) && (reg <= 32);
+
+ return save;
+}
+
+void
+ABISysV_hexagon::Initialize( void )
+{
+ PluginManager::RegisterPlugin
+ (
+ GetPluginNameStatic(),
+ "System V ABI for hexagon targets",
+ CreateInstance
+ );
+}
+
+void
+ABISysV_hexagon::Terminate( void )
+{
+ PluginManager::UnregisterPlugin( CreateInstance );
+}
+
+lldb_private::ConstString
+ABISysV_hexagon::GetPluginNameStatic()
+{
+ static ConstString g_name( "sysv-hexagon" );
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ABISysV_hexagon::GetPluginName( void )
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ABISysV_hexagon::GetPluginVersion( void )
+{
+ return 1;
+}
+
+// get value object specialized to work with llvm IR types
+lldb::ValueObjectSP
+ABISysV_hexagon::GetReturnValueObjectImpl( lldb_private::Thread &thread, llvm::Type &retType ) const
+{
+ Value value;
+ ValueObjectSP vObjSP;
+
+ // get the current register context
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return vObjSP;
+
+ // for now just pop R0 to find the return value
+ const lldb_private::RegisterInfo *r0_info = reg_ctx->GetRegisterInfoAtIndex( 0 );
+ if ( r0_info == nullptr )
+ return vObjSP;
+
+ // void return type
+ if ( retType.isVoidTy( ) )
+ {
+ value.GetScalar( ) = 0;
+ }
+ // integer / pointer return type
+ else
+ if ( retType.isIntegerTy( ) || retType.isPointerTy( ) )
+ {
+ // read r0 register value
+ lldb_private::RegisterValue r0_value;
+ if ( !reg_ctx->ReadRegister( r0_info, r0_value ) )
+ return vObjSP;
+
+ // push r0 into value
+ uint32_t r0_u32 = r0_value.GetAsUInt32( );
+
+ // account for integer size
+ if ( retType.isIntegerTy() && retType.isSized() )
+ {
+ uint64_t size = retType.getScalarSizeInBits( );
+ uint64_t mask = ( 1ull << size ) - 1;
+ // mask out higher order bits then the type we expect
+ r0_u32 &= mask;
+ }
+
+ value.GetScalar( ) = r0_u32;
+ }
+ // unsupported return type
+ else
+ return vObjSP;
+
+ // pack the value into a ValueObjectSP
+ vObjSP = ValueObjectConstResult::Create
+ (
+ thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString("")
+ );
+ return vObjSP;
+}
diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
new file mode 100644
index 000000000000..989c4a16710a
--- /dev/null
+++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
@@ -0,0 +1,148 @@
+//===-- ABISysV_hexagon.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_hexagon_h_
+#define liblldb_ABISysV_hexagon_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+class ABISysV_hexagon :
+ public lldb_private::ABI
+{
+public:
+
+ ~ABISysV_hexagon( void )
+ {
+ }
+
+ virtual size_t
+ GetRedZoneSize ( void ) const;
+
+ virtual bool
+ PrepareTrivialCall ( lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args ) const;
+
+ // special thread plan for GDB style non-jit function calls
+ virtual bool
+ PrepareTrivialCall ( lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::Type &prototype,
+ llvm::ArrayRef<ABI::CallArgument> 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;
+
+ // specialized to work with llvm IR types
+ virtual lldb::ValueObjectSP
+ GetReturnValueObjectImpl ( lldb_private::Thread &thread, llvm::Type &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 ( void )
+ {
+ return true;
+ }
+
+ virtual bool
+ CallFrameAddressIsValid ( lldb::addr_t cfa )
+ {
+ // Make sure the stack call frame addresses are 8 byte aligned
+ if (cfa & 0x07)
+ 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 ( void )
+ {
+ return true;
+ }
+
+ virtual const lldb_private::RegisterInfo *
+ GetRegisterInfoArray ( uint32_t &count );
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize ( void );
+
+ static void
+ Terminate ( void );
+
+ static lldb::ABISP
+ CreateInstance ( const lldb_private::ArchSpec &arch );
+
+ static lldb_private::ConstString
+ GetPluginNameStatic ( void );
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual lldb_private::ConstString
+ GetPluginName ( void );
+
+ virtual uint32_t
+ GetPluginVersion ( void );
+
+protected:
+ void
+ CreateRegisterMapIfNeeded ( void );
+
+ bool
+ RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
+
+private:
+ ABISysV_hexagon ( void ) : lldb_private::ABI() { } // Call CreateInstance instead.
+};
+
+#endif // liblldb_ABISysV_hexagon_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 a8ef6a51399c..b537415bf055 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -28,6 +28,7 @@
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Thread.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
using namespace lldb;
@@ -251,7 +252,7 @@ static RegisterInfo g_register_infos[] =
{ "ymm15" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm15 , gcc_dwarf_ymm15 , LLDB_INVALID_REGNUM , gdb_ymm15 , LLDB_INVALID_REGNUM }, NULL, NULL}
};
-static const uint32_t k_num_register_infos = sizeof(g_register_infos)/sizeof(RegisterInfo);
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
static bool g_register_info_names_constified = false;
const lldb_private::RegisterInfo *
@@ -316,8 +317,8 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
(uint64_t)func_addr,
(uint64_t)return_addr);
- for (int i = 0; i < args.size(); ++i)
- s.Printf (", arg%d = 0x%" PRIx64, i + 1, args[i]);
+ 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());
}
@@ -331,11 +332,11 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
if (args.size() > 6) // TODO handle more than 6 arguments
return false;
- for (int i = 0; i < args.size(); ++i)
+ 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%d (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);
+ 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;
}
@@ -562,7 +563,13 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("rax", 0);
DataExtractor data;
- size_t num_bytes = new_value_sp->GetData(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)
{
@@ -589,8 +596,14 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0);
RegisterValue xmm0_value;
DataExtractor data;
- size_t num_bytes = new_value_sp->GetData(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();
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index e9b8a9f573a3..c14371d0589c 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -10,10 +10,10 @@
#include "DisassemblerLLVMC.h"
#include "llvm-c/Disassembler.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCExternalSymbolizer.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrInfo.h"
@@ -48,7 +48,7 @@ class InstructionLLVMC : public lldb_private::Instruction
{
public:
InstructionLLVMC (DisassemblerLLVMC &disasm,
- const lldb_private::Address &address,
+ const lldb_private::Address &address,
AddressClass addr_class) :
Instruction (address, addr_class),
m_disasm_sp (disasm.shared_from_this()),
@@ -57,12 +57,12 @@ public:
m_using_file_addr (false)
{
}
-
+
virtual
~InstructionLLVMC ()
{
}
-
+
virtual bool
DoesBranch ()
{
@@ -99,7 +99,7 @@ public:
}
return m_does_branch == eLazyBoolYes;
}
-
+
DisassemblerLLVMC::LLVMCDisassembler *
GetDisasmToUse (bool &is_alternate_isa)
{
@@ -108,7 +108,7 @@ public:
if (llvm_disasm.m_alternate_disasm_ap.get() != NULL)
{
const AddressClass address_class = GetAddressClass ();
-
+
if (address_class == eAddressClassCodeAlternateISA)
{
is_alternate_isa = true;
@@ -117,7 +117,7 @@ public:
}
return llvm_disasm.m_disasm_ap.get();
}
-
+
virtual size_t
Decode (const lldb_private::Disassembler &disassembler,
const lldb_private::DataExtractor &data,
@@ -129,7 +129,7 @@ public:
DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
const ArchSpec &arch = llvm_disasm.GetArchitecture();
const lldb::ByteOrder byte_order = data.GetByteOrder();
-
+
const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
if (min_op_byte_size == max_op_byte_size)
@@ -170,7 +170,7 @@ public:
{
bool is_alternate_isa = false;
DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
-
+
const llvm::Triple::ArchType machine = arch.GetMachine();
if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb)
{
@@ -204,7 +204,7 @@ public:
const size_t opcode_data_len = data.BytesLeft(data_offset);
const addr_t pc = m_address.GetFileAddress();
llvm::MCInst inst;
-
+
llvm_disasm.Lock(this, NULL);
const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data,
opcode_data_len,
@@ -222,7 +222,7 @@ public:
}
return m_opcode.GetByteSize();
}
-
+
void
AppendComment (std::string &description)
{
@@ -234,7 +234,7 @@ public:
m_comment.append(description);
}
}
-
+
virtual void
CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx)
{
@@ -244,19 +244,19 @@ public:
if (m_opcode.GetData(data))
{
char out_string[512];
-
+
DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr;
-
+
if (address_class == eAddressClassCodeAlternateISA)
mc_disasm_ptr = llvm_disasm.m_alternate_disasm_ap.get();
else
mc_disasm_ptr = llvm_disasm.m_disasm_ap.get();
-
+
lldb::addr_t pc = m_address.GetFileAddress();
m_using_file_addr = true;
-
+
const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file;
bool use_hex_immediates = true;
Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC;
@@ -280,9 +280,9 @@ public:
}
}
}
-
+
llvm_disasm.Lock(this, exe_ctx);
-
+
const uint8_t *opcode_data = data.GetDataStart();
const size_t opcode_data_len = data.GetByteSize();
llvm::MCInst inst;
@@ -298,7 +298,7 @@ public:
}
llvm_disasm.Unlock();
-
+
if (inst_size == 0)
{
m_comment.assign ("unknown opcode");
@@ -371,11 +371,11 @@ public:
}
}
-
+
static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED);
-
+
RegularExpression::Match matches(3);
-
+
if (s_regex.Execute(out_string, &matches))
{
matches.GetMatchAtIndex(out_string, 1, m_opcode_name);
@@ -383,13 +383,13 @@ public:
}
}
}
-
+
bool
IsValid () const
{
return m_is_valid;
}
-
+
bool
UsingFileAddress() const
{
@@ -400,14 +400,14 @@ public:
{
return m_opcode.GetByteSize();
}
-
+
DisassemblerLLVMC &
GetDisassemblerLLVMC ()
{
return *(DisassemblerLLVMC *)m_disasm_sp.get();
}
protected:
-
+
DisassemblerSP m_disasm_sp; // for ownership
LazyBool m_does_branch;
bool m_is_valid;
@@ -426,15 +426,15 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, uns
m_is_valid = false;
return;
}
-
+
m_instr_info_ap.reset(curr_target->createMCInstrInfo());
m_reg_info_ap.reset (curr_target->createMCRegInfo(triple));
-
+
std::string features_str;
m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, "",
features_str));
-
+
std::unique_ptr<llvm::MCRegisterInfo> reg_info(curr_target->createMCRegInfo(triple));
m_asm_info_ap.reset(curr_target->createMCAsmInfo(*reg_info, triple));
@@ -443,24 +443,25 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, uns
m_is_valid = false;
return;
}
-
+
m_context_ap.reset(new llvm::MCContext(m_asm_info_ap.get(), m_reg_info_ap.get(), 0));
-
- m_disasm_ap.reset(curr_target->createMCDisassembler(*m_subtarget_info_ap.get()));
+
+ m_disasm_ap.reset(curr_target->createMCDisassembler(*m_subtarget_info_ap.get(), *m_context_ap.get()));
if (m_disasm_ap.get() && m_context_ap.get())
{
- llvm::OwningPtr<llvm::MCRelocationInfo> RelInfo(curr_target->createMCRelocationInfo(triple, *m_context_ap.get()));
+ std::unique_ptr<llvm::MCRelocationInfo> RelInfo(curr_target->createMCRelocationInfo(triple, *m_context_ap.get()));
if (!RelInfo)
{
m_is_valid = false;
return;
}
- m_disasm_ap->setupForSymbolicDisassembly(NULL,
- DisassemblerLLVMC::SymbolLookupCallback,
- (void *) &owner,
- m_context_ap.get(),
- RelInfo);
-
+ std::unique_ptr<llvm::MCSymbolizer> symbolizer_up(curr_target->createMCSymbolizer(triple, NULL,
+ DisassemblerLLVMC::SymbolLookupCallback,
+ (void *) &owner,
+ m_context_ap.get(), RelInfo.release()));
+ m_disasm_ap->setSymbolizer(std::move(symbolizer_up));
+
+
unsigned asm_printer_variant;
if (flavor == ~0U)
asm_printer_variant = m_asm_info_ap->getAssemblerDialect();
@@ -468,7 +469,7 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, uns
{
asm_printer_variant = flavor;
}
-
+
m_instr_printer_ap.reset(curr_target->createMCInstPrinter(asm_printer_variant,
*m_asm_info_ap.get(),
*m_instr_info_ap.get(),
@@ -497,7 +498,7 @@ namespace {
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; }
@@ -545,7 +546,7 @@ DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst,
const size_t output_size = std::min(dst_len - 1, inst_string.size());
std::memcpy(dst, inst_string.data(), output_size);
dst[output_size] = '\0';
-
+
return output_size;
}
@@ -572,7 +573,7 @@ DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, c
llvm::Triple triple = arch.GetTriple();
if (flavor == NULL || strcmp (flavor, "default") == 0)
return true;
-
+
if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
{
if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0)
@@ -583,7 +584,7 @@ DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, c
else
return false;
}
-
+
Disassembler *
DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
@@ -591,7 +592,7 @@ DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch)
{
std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor));
-
+
if (disasm_ap.get() && disasm_ap->IsValid())
return disasm_ap.release();
}
@@ -608,10 +609,10 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
{
m_flavor.assign("default");
}
-
+
const char *triple = arch.GetTriple().getTriple().c_str();
unsigned flavor = ~0U;
-
+
// So far the only supported flavor is "intel" on x86. The base class will set this
// correctly coming in.
if (arch.GetTriple().getArch() == llvm::Triple::x86
@@ -626,7 +627,7 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
flavor = 0;
}
}
-
+
ArchSpec thumb_arch(arch);
if (arch.GetTriple().getArch() == llvm::Triple::arm)
{
@@ -643,15 +644,15 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
}
thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str()));
}
-
- // Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions,
+
+ // Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions,
// so hardcode the primary disassembler to thumb mode. Same for Cortex-M4 (armv7em).
//
// Handle the Cortex-M0 (armv6m) the same; the ISA is a subset of the T and T32
- // instructions defined in ARMv7-A.
+ // instructions defined in ARMv7-A.
if (arch.GetTriple().getArch() == llvm::Triple::arm
- && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m
+ && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m
|| arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em
|| arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m))
{
@@ -693,33 +694,33 @@ DisassemblerLLVMC::DecodeInstructions (const Address &base_addr,
{
if (!append)
m_instruction_list.Clear();
-
+
if (!IsValid())
return 0;
-
+
m_data_from_file = data_from_file;
uint32_t data_cursor = data_offset;
const size_t data_byte_size = data.GetByteSize();
uint32_t instructions_parsed = 0;
Address inst_addr(base_addr);
-
+
while (data_cursor < data_byte_size && instructions_parsed < num_instructions)
{
-
+
AddressClass address_class = eAddressClassCode;
-
+
if (m_alternate_disasm_ap.get() != NULL)
address_class = inst_addr.GetAddressClass ();
-
+
InstructionSP inst_sp(new InstructionLLVMC(*this,
- inst_addr,
+ inst_addr,
address_class));
-
+
if (!inst_sp)
break;
-
+
uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor);
-
+
if (inst_size == 0)
break;
@@ -728,7 +729,7 @@ DisassemblerLLVMC::DecodeInstructions (const Address &base_addr,
inst_addr.Slide(inst_size);
instructions_parsed++;
}
-
+
return data_cursor - data_offset;
}
@@ -736,9 +737,9 @@ void
DisassemblerLLVMC::Initialize()
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
- "Disassembler that uses LLVM MC to disassemble i386, x86_64 and ARM.",
+ "Disassembler that uses LLVM MC to disassemble i386, x86_64, ARM, and ARM64.",
CreateInstance);
-
+
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
@@ -810,7 +811,7 @@ const char *DisassemblerLLVMC::SymbolLookup (uint64_t value,
if (*type_ptr)
{
if (m_exe_ctx && m_inst)
- {
+ {
//std::string remove_this_prior_to_checkin;
Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : NULL;
Address value_so_addr;
@@ -824,16 +825,16 @@ const char *DisassemblerLLVMC::SymbolLookup (uint64_t value,
{
target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr);
}
-
+
if (value_so_addr.IsValid() && value_so_addr.GetSection())
{
StreamString ss;
-
+
value_so_addr.Dump (&ss,
target,
Address::DumpStyleResolvedDescriptionNoModule,
Address::DumpStyleSectionNameOffset);
-
+
if (!ss.GetString().empty())
{
m_inst->AppendComment(ss.GetString());
@@ -861,4 +862,3 @@ DisassemblerLLVMC::GetPluginVersion()
{
return 1;
}
-
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
index c567791866d5..6ab9e9ae2625 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
@@ -42,9 +42,9 @@ class DisassemblerLLVMC : public lldb_private::Disassembler
{
public:
LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner);
-
+
~LLVMCDisassembler();
-
+
uint64_t GetMCInst (const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst);
uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len);
void SetStyle (bool use_hex_immed, HexImmediateStyle hex_style);
@@ -53,7 +53,7 @@ class DisassemblerLLVMC : public lldb_private::Disassembler
{
return m_is_valid;
}
-
+
private:
bool m_is_valid;
std::unique_ptr<llvm::MCContext> m_context_ap;
@@ -71,21 +71,21 @@ public:
//------------------------------------------------------------------
static void
Initialize();
-
+
static void
Terminate();
-
+
static lldb_private::ConstString
GetPluginNameStatic();
-
+
static lldb_private::Disassembler *
CreateInstance(const lldb_private::ArchSpec &arch, const char *flavor);
-
+
DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */);
-
+
virtual
~DisassemblerLLVMC();
-
+
virtual size_t
DecodeInstructions (const lldb_private::Address &base_addr,
const lldb_private::DataExtractor& data,
@@ -93,72 +93,72 @@ public:
size_t num_instructions,
bool append,
bool data_from_file);
-
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
virtual lldb_private::ConstString
GetPluginName();
-
+
virtual uint32_t
GetPluginVersion();
-
+
protected:
friend class InstructionLLVMC;
-
+
virtual bool
FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor);
-
+
bool
IsValid()
{
return (m_disasm_ap.get() != NULL && m_disasm_ap->IsValid());
}
-
+
int OpInfo(uint64_t PC,
uint64_t Offset,
uint64_t Size,
int TagType,
void *TagBug);
-
+
const char *SymbolLookup (uint64_t ReferenceValue,
uint64_t *ReferenceType,
uint64_t ReferencePC,
const char **ReferenceName);
-
+
static int OpInfoCallback (void *DisInfo,
uint64_t PC,
uint64_t Offset,
uint64_t Size,
int TagType,
void *TagBug);
-
+
static const char *SymbolLookupCallback(void *DisInfo,
uint64_t ReferenceValue,
uint64_t *ReferenceType,
uint64_t ReferencePC,
const char **ReferenceName);
-
- void Lock(InstructionLLVMC *inst,
+
+ void Lock(InstructionLLVMC *inst,
const lldb_private::ExecutionContext *exe_ctx)
{
m_mutex.Lock();
m_inst = inst;
m_exe_ctx = exe_ctx;
}
-
+
void Unlock()
{
m_inst = NULL;
m_exe_ctx = NULL;
m_mutex.Unlock();
}
-
+
const lldb_private::ExecutionContext *m_exe_ctx;
InstructionLLVMC *m_inst;
lldb_private::Mutex m_mutex;
bool m_data_from_file;
-
+
std::unique_ptr<LLVMCDisassembler> m_disasm_ap;
std::unique_ptr<LLVMCDisassembler> m_alternate_disasm_ap;
};
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
new file mode 100644
index 000000000000..c79d96abafa2
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
@@ -0,0 +1,727 @@
+//===-- DynamicLoaderHexagon.h ----------------------------------*- 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
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+
+#include "DynamicLoaderHexagonDYLD.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// Aidan 21/05/2014
+//
+// Notes about hexagon dynamic loading:
+//
+// When we connect to a target we find the dyld breakpoint address. We put a
+// breakpoint there with a callback 'RendezvousBreakpointHit()'.
+//
+// It is possible to find the dyld structure address from the ELF symbol table,
+// but in the case of the simulator it has not been initialized before the
+// target calls dlinit().
+//
+// We can only safely parse the dyld structure after we hit the dyld breakpoint
+// since at that time we know dlinit() must have been called.
+//
+
+// Find the load address of a symbol
+static lldb::addr_t findSymbolAddress( Process *proc, ConstString findName )
+{
+ assert( proc != nullptr );
+
+ ModuleSP module = proc->GetTarget().GetExecutableModule();
+ assert( module.get() != nullptr );
+
+ ObjectFile *exe = module->GetObjectFile();
+ assert( exe != nullptr );
+
+ lldb_private::Symtab *symtab = exe->GetSymtab( );
+ assert( symtab != nullptr );
+
+ for ( size_t i = 0; i < symtab->GetNumSymbols( ); i++ )
+ {
+ const Symbol* sym = symtab->SymbolAtIndex( i );
+ assert( sym != nullptr );
+ const ConstString &symName = sym->GetName( );
+
+ if ( ConstString::Compare( findName, symName ) == 0 )
+ {
+ Address addr = sym->GetAddress( );
+ return addr.GetLoadAddress( & proc->GetTarget() );
+ }
+ }
+ return LLDB_INVALID_ADDRESS;
+}
+
+void
+DynamicLoaderHexagonDYLD::Initialize()
+{
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ CreateInstance);
+}
+
+void
+DynamicLoaderHexagonDYLD::Terminate()
+{
+}
+
+lldb_private::ConstString
+DynamicLoaderHexagonDYLD::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+lldb_private::ConstString
+DynamicLoaderHexagonDYLD::GetPluginNameStatic()
+{
+ static ConstString g_name("hexagon-dyld");
+ return g_name;
+}
+
+const char *
+DynamicLoaderHexagonDYLD::GetPluginDescriptionStatic()
+{
+ return "Dynamic loader plug-in that watches for shared library "
+ "loads/unloads in Hexagon processes.";
+}
+
+void
+DynamicLoaderHexagonDYLD::GetPluginCommandHelp(const char *command, Stream *strm)
+{
+}
+
+uint32_t
+DynamicLoaderHexagonDYLD::GetPluginVersion()
+{
+ return 1;
+}
+
+DynamicLoader *
+DynamicLoaderHexagonDYLD::CreateInstance(Process *process, bool force)
+{
+ bool create = force;
+ if (!create)
+ {
+ const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
+ if (triple_ref.getArch() == llvm::Triple::hexagon)
+ create = true;
+ }
+
+ if (create)
+ return new DynamicLoaderHexagonDYLD(process);
+ return NULL;
+}
+
+DynamicLoaderHexagonDYLD::DynamicLoaderHexagonDYLD(Process *process)
+ : DynamicLoader(process)
+ , m_rendezvous (process)
+ , m_load_offset(LLDB_INVALID_ADDRESS)
+ , m_entry_point(LLDB_INVALID_ADDRESS)
+ , m_dyld_bid (LLDB_INVALID_BREAK_ID)
+{
+}
+
+DynamicLoaderHexagonDYLD::~DynamicLoaderHexagonDYLD()
+{
+ if (m_dyld_bid != LLDB_INVALID_BREAK_ID)
+ {
+ m_process->GetTarget().RemoveBreakpointByID (m_dyld_bid);
+ m_dyld_bid = LLDB_INVALID_BREAK_ID;
+ }
+}
+
+void
+DynamicLoaderHexagonDYLD::DidAttach()
+{
+ ModuleSP executable;
+ addr_t load_offset;
+
+ executable = GetTargetExecutable();
+
+ // Find the difference between the desired load address in the elf file
+ // and the real load address in memory
+ load_offset = ComputeLoadOffset();
+
+ // Check that there is a valid executable
+ if ( executable.get( ) == nullptr )
+ return;
+
+ // Disable JIT for hexagon targets because its not supported
+ m_process->SetCanJIT(false);
+
+ // Add the current executable to the module list
+ ModuleList module_list;
+ module_list.Append(executable);
+
+ // Map the loaded sections of this executable
+ if ( load_offset != LLDB_INVALID_ADDRESS )
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
+
+ // AD: confirm this?
+ // Load into LLDB all of the currently loaded executables in the stub
+ LoadAllCurrentModules();
+
+ // AD: confirm this?
+ // Callback for the target to give it the loaded module list
+ m_process->GetTarget().ModulesDidLoad(module_list);
+
+ // Try to set a breakpoint at the rendezvous breakpoint.
+ // DidLaunch uses ProbeEntry() instead. That sets a breakpoint,
+ // at the dyld breakpoint address, with a callback so that when hit,
+ // the dyld structure can be parsed.
+ if (! SetRendezvousBreakpoint() )
+ {
+ // fail
+ }
+}
+
+void
+DynamicLoaderHexagonDYLD::DidLaunch()
+{
+}
+
+/// Checks to see if the target module has changed, updates the target
+/// accordingly and returns the target executable module.
+ModuleSP
+DynamicLoaderHexagonDYLD::GetTargetExecutable()
+{
+ Target &target = m_process->GetTarget();
+ ModuleSP executable = target.GetExecutableModule();
+
+ // There is no executable
+ if (! executable.get())
+ return executable;
+
+ // The target executable file does not exits
+ if (! executable->GetFileSpec().Exists())
+ return executable;
+
+ // Prep module for loading
+ ModuleSpec module_spec(executable->GetFileSpec(), executable->GetArchitecture());
+ ModuleSP module_sp (new Module (module_spec));
+
+ // Check if the executable has changed and set it to the target executable if they differ.
+ if (module_sp.get() && module_sp->GetUUID().IsValid() && executable->GetUUID().IsValid())
+ {
+ // if the executable has changed ??
+ if (module_sp->GetUUID() != executable->GetUUID())
+ executable.reset();
+ }
+ else if (executable->FileHasChanged())
+ executable.reset();
+
+ if ( executable.get( ) )
+ return executable;
+
+ // TODO: What case is this code used?
+ executable = target.GetSharedModule(module_spec);
+ if (executable.get() != target.GetExecutableModulePointer())
+ {
+ // Don't load dependent images since we are in dyld where we will know
+ // and find out about all images that are loaded
+ const bool get_dependent_images = false;
+ target.SetExecutableModule(executable, get_dependent_images);
+ }
+
+ return executable;
+}
+
+Error
+DynamicLoaderHexagonDYLD::ExecutePluginCommand(Args &command, Stream *strm)
+{
+ return Error();
+}
+
+Log *
+DynamicLoaderHexagonDYLD::EnablePluginLogging(Stream *strm, Args &command)
+{
+ return NULL;
+}
+
+//AD: Needs to be updated?
+Error
+DynamicLoaderHexagonDYLD::CanLoadImage()
+{
+ return Error();
+}
+
+void
+DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
+{
+ Target &target = m_process->GetTarget();
+ const SectionList *sections = GetSectionListFromModule(module);
+
+ assert(sections && "SectionList missing from loaded module.");
+
+ m_loaded_modules[module] = link_map_addr;
+
+ const size_t num_sections = sections->GetSize();
+
+ for (unsigned i = 0; i < num_sections; ++i)
+ {
+ SectionSP section_sp (sections->GetSectionAtIndex(i));
+ lldb::addr_t new_load_addr = section_sp->GetFileAddress() + base_addr;
+
+ // AD: 02/05/14
+ // since our memory map starts from address 0, we must not ignore
+ // sections that load to address 0. This violates the reference
+ // ELF spec, however is used for Hexagon.
+
+ // If the file address of the section is zero then this is not an
+ // allocatable/loadable section (property of ELF sh_addr). Skip it.
+// if (new_load_addr == base_addr)
+// continue;
+
+ target.SetSectionLoadAddress(section_sp, new_load_addr);
+ }
+}
+
+/// Removes the loaded sections from the target in @p module.
+///
+/// @param module The module to traverse.
+void
+DynamicLoaderHexagonDYLD::UnloadSections(const ModuleSP module)
+{
+ Target &target = m_process->GetTarget();
+ const SectionList *sections = GetSectionListFromModule(module);
+
+ assert(sections && "SectionList missing from unloaded module.");
+
+ m_loaded_modules.erase(module);
+
+ const size_t num_sections = sections->GetSize();
+ for (size_t i = 0; i < num_sections; ++i)
+ {
+ SectionSP section_sp (sections->GetSectionAtIndex(i));
+ target.SetSectionUnloaded(section_sp);
+ }
+}
+
+// Place a breakpoint on <_rtld_debug_state>
+bool
+DynamicLoaderHexagonDYLD::SetRendezvousBreakpoint()
+{
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
+ // This is the original code, which want to look in the rendezvous structure
+ // to find the breakpoint address. Its backwards for us, since we can easily
+ // find the breakpoint address, since it is exported in our executable.
+ // We however know that we cant read the Rendezvous structure until we have hit
+ // the breakpoint once.
+ const ConstString dyldBpName( "_rtld_debug_state" );
+ addr_t break_addr = findSymbolAddress( m_process, dyldBpName );
+
+ Target &target = m_process->GetTarget();
+
+ // Do not try to set the breakpoint if we don't know where to put it
+ if ( break_addr == LLDB_INVALID_ADDRESS )
+ {
+ if ( log )
+ log->Printf( "Unable to locate _rtld_debug_state breakpoint address" );
+
+ return false;
+ }
+
+ // Save the address of the rendezvous structure
+ m_rendezvous.SetBreakAddress( break_addr );
+
+ // If we haven't set the breakpoint before then set it
+ if (m_dyld_bid == LLDB_INVALID_BREAK_ID)
+ {
+ 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();
+
+ // Make sure our breakpoint is at the right address.
+ assert
+ (
+ target.GetBreakpointByID(m_dyld_bid)->
+ FindLocationByAddress(break_addr)->
+ GetBreakpoint().GetID()
+ == m_dyld_bid
+ );
+
+ if ( log && dyld_break == nullptr )
+ log->Printf( "Failed to create _rtld_debug_state breakpoint" );
+
+ // check we have successfully set bp
+ return (dyld_break != nullptr);
+ }
+ else
+ // rendezvous already set
+ return true;
+}
+
+// We have just hit our breakpoint at <_rtld_debug_state>
+bool
+DynamicLoaderHexagonDYLD::RendezvousBreakpointHit(void *baton,
+ StoppointCallbackContext *context,
+ user_id_t break_id,
+ user_id_t break_loc_id)
+{
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
+ if ( log )
+ log->Printf( "Rendezvous breakpoint hit!" );
+
+ DynamicLoaderHexagonDYLD* dyld_instance = nullptr;
+ dyld_instance = static_cast<DynamicLoaderHexagonDYLD*>(baton);
+
+ // if the dyld_instance is still not valid then
+ // try to locate it on the symbol table
+ if ( !dyld_instance->m_rendezvous.IsValid( ) )
+ {
+ Process *proc = dyld_instance->m_process;
+
+ const ConstString dyldStructName( "_rtld_debug" );
+ addr_t structAddr = findSymbolAddress( proc, dyldStructName );
+
+ if ( structAddr != LLDB_INVALID_ADDRESS )
+ {
+ dyld_instance->m_rendezvous.SetRendezvousAddress( structAddr );
+
+ if ( log )
+ log->Printf( "Found _rtld_debug structure @ 0x%08lx", structAddr );
+ }
+ else
+ {
+ if ( log )
+ log->Printf( "Unable to resolve the _rtld_debug structure" );
+ }
+ }
+
+ dyld_instance->RefreshModules();
+
+ // Return true to stop the target, false to just let the target run.
+ return dyld_instance->GetStopWhenImagesChange();
+}
+
+/// Helper method for RendezvousBreakpointHit. Updates LLDB's current set
+/// of loaded modules.
+void
+DynamicLoaderHexagonDYLD::RefreshModules()
+{
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
+ if (!m_rendezvous.Resolve())
+ return;
+
+ HexagonDYLDRendezvous::iterator I;
+ HexagonDYLDRendezvous::iterator E;
+
+ ModuleList &loaded_modules = m_process->GetTarget().GetImages();
+
+ if (m_rendezvous.ModulesDidLoad())
+ {
+ ModuleList new_modules;
+
+ E = m_rendezvous.loaded_end();
+ for (I = m_rendezvous.loaded_begin(); I != E; ++I)
+ {
+ FileSpec file(I->path.c_str(), true);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
+ if (module_sp.get())
+ {
+ loaded_modules.AppendIfNeeded( module_sp );
+ new_modules.Append(module_sp);
+ }
+
+ if (log)
+ {
+ log->Printf( "Target is loading '%s'", I->path.c_str() );
+ if (! module_sp.get() )
+ log->Printf( "LLDB failed to load '%s'", I->path.c_str() );
+ else
+ log->Printf( "LLDB successfully loaded '%s'", I->path.c_str() );
+ }
+
+ }
+ m_process->GetTarget().ModulesDidLoad(new_modules);
+ }
+
+ if (m_rendezvous.ModulesDidUnload())
+ {
+ ModuleList old_modules;
+
+ E = m_rendezvous.unloaded_end();
+ for (I = m_rendezvous.unloaded_begin(); I != E; ++I)
+ {
+ FileSpec file(I->path.c_str(), true);
+ ModuleSpec module_spec(file);
+ ModuleSP module_sp = loaded_modules.FindFirstModule (module_spec);
+
+ if (module_sp.get())
+ {
+ old_modules.Append(module_sp);
+ UnloadSections(module_sp);
+ }
+
+ if (log)
+ log->Printf( "Target is unloading '%s'", I->path.c_str() );
+
+ }
+ loaded_modules.Remove(old_modules);
+ m_process->GetTarget().ModulesDidUnload(old_modules, false);
+ }
+}
+
+//AD: This is very different to the Static Loader code.
+// It may be wise to look over this and its relation to stack
+// unwinding.
+ThreadPlanSP
+DynamicLoaderHexagonDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop)
+{
+ ThreadPlanSP thread_plan_sp;
+
+ StackFrame *frame = thread.GetStackFrameAtIndex(0).get();
+ const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol);
+ Symbol *sym = context.symbol;
+
+ if (sym == NULL || !sym->IsTrampoline())
+ return thread_plan_sp;
+
+ const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);
+ if (!sym_name)
+ return thread_plan_sp;
+
+ SymbolContextList target_symbols;
+ Target &target = thread.GetProcess()->GetTarget();
+ const ModuleList &images = target.GetImages();
+
+ images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols);
+ size_t num_targets = target_symbols.GetSize();
+ if (!num_targets)
+ return thread_plan_sp;
+
+ typedef std::vector<lldb::addr_t> AddressVector;
+ AddressVector addrs;
+ for (size_t i = 0; i < num_targets; ++i)
+ {
+ SymbolContext context;
+ AddressRange range;
+ if (target_symbols.GetContextAtIndex(i, context))
+ {
+ context.GetAddressRange(eSymbolContextEverything, 0, false, range);
+ lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target);
+ if (addr != LLDB_INVALID_ADDRESS)
+ addrs.push_back(addr);
+ }
+ }
+
+ if (addrs.size() > 0)
+ {
+ AddressVector::iterator start = addrs.begin();
+ AddressVector::iterator end = addrs.end();
+
+ std::sort(start, end);
+ addrs.erase(std::unique(start, end), end);
+ thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop));
+ }
+
+ return thread_plan_sp;
+}
+
+/// Helper for the entry breakpoint callback. Resolves the load addresses
+/// of all dependent modules.
+void
+DynamicLoaderHexagonDYLD::LoadAllCurrentModules()
+{
+ HexagonDYLDRendezvous::iterator I;
+ HexagonDYLDRendezvous::iterator E;
+ ModuleList module_list;
+
+ if (!m_rendezvous.Resolve())
+ {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (log)
+ log->Printf("DynamicLoaderHexagonDYLD::%s unable to resolve rendezvous address", __FUNCTION__);
+ return;
+ }
+
+ // The rendezvous class doesn't enumerate the main module, so track
+ // that ourselves here.
+ ModuleSP executable = GetTargetExecutable();
+ m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();
+
+
+ for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
+ {
+ const char *module_path = I->path.c_str();
+ FileSpec file(module_path, false);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
+ if (module_sp.get())
+ {
+ module_list.Append(module_sp);
+ }
+ else
+ {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (log)
+ log->Printf("DynamicLoaderHexagonDYLD::%s failed loading module %s at 0x%" PRIx64,
+ __FUNCTION__, module_path, I->base_addr);
+ }
+ }
+
+ m_process->GetTarget().ModulesDidLoad(module_list);
+}
+
+/// Helper for the entry breakpoint callback. Resolves the load addresses
+/// of all dependent modules.
+ModuleSP
+DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr)
+{
+ Target &target = m_process->GetTarget();
+ ModuleList &modules = target.GetImages();
+ ModuleSP module_sp;
+
+ ModuleSpec module_spec (file, target.GetArchitecture());
+
+ // check if module is currently loaded
+ if ((module_sp = modules.FindFirstModule (module_spec)))
+ {
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ }
+ // try to load this module from disk
+ else if ((module_sp = target.GetSharedModule(module_spec)))
+ {
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ }
+
+ return module_sp;
+}
+
+/// Computes a value for m_load_offset returning the computed address on
+/// success and LLDB_INVALID_ADDRESS on failure.
+addr_t
+DynamicLoaderHexagonDYLD::ComputeLoadOffset()
+{
+ // Here we could send a GDB packet to know the load offset
+ //
+ // send: $qOffsets#4b
+ // get: Text=0;Data=0;Bss=0
+ //
+ // Currently qOffsets is not supported by pluginProcessGDBRemote
+ //
+ return 0;
+}
+
+// Here we must try to read the entry point directly from
+// the elf header. This is possible if the process is not
+// relocatable or dynamically linked.
+//
+// an alternative is to look at the PC if we can be sure
+// that we have connected when the process is at the entry point.
+// I dont think that is reliable for us.
+addr_t
+DynamicLoaderHexagonDYLD::GetEntryPoint()
+{
+ if (m_entry_point != LLDB_INVALID_ADDRESS)
+ return m_entry_point;
+ // check we have a valid process
+ if ( m_process == nullptr )
+ return LLDB_INVALID_ADDRESS;
+ // Get the current executable module
+ Module & module = *( m_process->GetTarget( ).GetExecutableModule( ).get( ) );
+ // Get the object file (elf file) for this module
+ lldb_private::ObjectFile &object = *( module.GetObjectFile( ) );
+ // Check if the file is executable (ie, not shared object or relocatable)
+ if ( object.IsExecutable() )
+ {
+ // Get the entry point address for this object
+ lldb_private::Address entry = object.GetEntryPointAddress( );
+ // Return the entry point address
+ return entry.GetFileAddress( );
+ }
+ // No idea so back out
+ return LLDB_INVALID_ADDRESS;
+}
+
+const SectionList *
+DynamicLoaderHexagonDYLD::GetSectionListFromModule(const ModuleSP module) const
+{
+ SectionList *sections = nullptr;
+ if (module.get())
+ {
+ ObjectFile *obj_file = module->GetObjectFile();
+ if (obj_file)
+ {
+ sections = obj_file->GetSectionList();
+ }
+ }
+ return sections;
+}
+
+static int ReadInt(Process *process, addr_t addr)
+{
+ Error error;
+ int value = (int)process->ReadUnsignedIntegerFromMemory(addr, sizeof(uint32_t), 0, error);
+ if (error.Fail())
+ return -1;
+ else
+ return value;
+}
+
+lldb::addr_t
+DynamicLoaderHexagonDYLD::GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread)
+{
+ auto it = m_loaded_modules.find (module);
+ if (it == m_loaded_modules.end())
+ return LLDB_INVALID_ADDRESS;
+
+ addr_t link_map = it->second;
+ if (link_map == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ const HexagonDYLDRendezvous::ThreadInfo &metadata = m_rendezvous.GetThreadInfo();
+ if (!metadata.valid)
+ return LLDB_INVALID_ADDRESS;
+
+ // Get the thread pointer.
+ addr_t tp = thread->GetThreadPointer ();
+ if (tp == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ // Find the module's modid.
+ int modid = ReadInt (m_process, link_map + metadata.modid_offset);
+ if (modid == -1)
+ return LLDB_INVALID_ADDRESS;
+
+ // Lookup the DTV stucture for this thread.
+ addr_t dtv_ptr = tp + metadata.dtv_offset;
+ addr_t dtv = ReadPointer (dtv_ptr);
+ if (dtv == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ // Find the TLS block for this module.
+ addr_t dtv_slot = dtv + metadata.dtv_slot_size*modid;
+ addr_t tls_block = ReadPointer (dtv_slot + metadata.tls_offset);
+
+ Module *mod = module.get();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (log)
+ log->Printf("DynamicLoaderHexagonDYLD::Performed TLS lookup: "
+ "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%i, tls_block=0x%" PRIx64,
+ mod->GetObjectName().AsCString(""), link_map, tp, modid, tls_block);
+
+ return tls_block;
+}
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
new file mode 100644
index 000000000000..aafa385c0fca
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
@@ -0,0 +1,182 @@
+//===-- DynamicLoaderHexagon.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_DynamicLoaderHexagon_H_
+#define liblldb_DynamicLoaderHexagon_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Target/DynamicLoader.h"
+
+#include "HexagonDYLDRendezvous.h"
+
+class DynamicLoaderHexagonDYLD : public lldb_private::DynamicLoader
+{
+public:
+
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ static lldb_private::DynamicLoader *
+ CreateInstance(lldb_private::Process *process, bool force);
+
+ DynamicLoaderHexagonDYLD(lldb_private::Process *process);
+
+ virtual
+ ~DynamicLoaderHexagonDYLD();
+
+ //------------------------------------------------------------------
+ // DynamicLoader protocol
+ //------------------------------------------------------------------
+
+ virtual void
+ DidAttach();
+
+ virtual void
+ DidLaunch();
+
+ virtual lldb::ThreadPlanSP
+ GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
+ bool stop_others);
+
+ virtual lldb_private::Error
+ CanLoadImage();
+
+ virtual lldb::addr_t
+ GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread);
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual lldb_private::ConstString
+ GetPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+ virtual void
+ GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
+
+ virtual lldb_private::Error
+ ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);
+
+ virtual lldb_private::Log *
+ EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);
+
+protected:
+ /// Runtime linker rendezvous structure.
+ HexagonDYLDRendezvous m_rendezvous;
+
+ /// Virtual load address of the inferior process.
+ lldb::addr_t m_load_offset;
+
+ /// Virtual entry address of the inferior process.
+ lldb::addr_t m_entry_point;
+
+ /// Rendezvous breakpoint.
+ lldb::break_id_t m_dyld_bid;
+
+ /// Loaded module list. (link map for each module)
+ std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>> m_loaded_modules;
+
+ /// Enables a breakpoint on a function called by the runtime
+ /// linker each time a module is loaded or unloaded.
+ bool
+ SetRendezvousBreakpoint();
+
+ /// Callback routine which updates the current list of loaded modules based
+ /// on the information supplied by the runtime linker.
+ static bool
+ RendezvousBreakpointHit(void *baton,
+ lldb_private::StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set
+ /// of loaded modules.
+ void
+ RefreshModules();
+
+ /// Updates the load address of every allocatable section in @p module.
+ ///
+ /// @param module The module to traverse.
+ ///
+ /// @param link_map_addr The virtual address of the link map for the @p module.
+ ///
+ /// @param base_addr The virtual base address @p module is loaded at.
+ void
+ UpdateLoadedSections(lldb::ModuleSP module,
+ lldb::addr_t link_map_addr,
+ lldb::addr_t base_addr);
+
+ /// Removes the loaded sections from the target in @p module.
+ ///
+ /// @param module The module to traverse.
+ void
+ UnloadSections(const lldb::ModuleSP module);
+
+ /// Locates or creates a module given by @p file and updates/loads the
+ /// resulting module at the virtual base address @p base_addr.
+ lldb::ModuleSP
+ LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr);
+
+ /// Callback routine invoked when we hit the breakpoint on process entry.
+ ///
+ /// This routine is responsible for resolving the load addresses of all
+ /// dependent modules required by the inferior and setting up the rendezvous
+ /// breakpoint.
+ static bool
+ EntryBreakpointHit(void *baton,
+ lldb_private::StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ /// Helper for the entry breakpoint callback. Resolves the load addresses
+ /// of all dependent modules.
+ void
+ LoadAllCurrentModules();
+
+ /// Computes a value for m_load_offset returning the computed address on
+ /// success and LLDB_INVALID_ADDRESS on failure.
+ lldb::addr_t
+ ComputeLoadOffset();
+
+ /// Computes a value for m_entry_point returning the computed address on
+ /// success and LLDB_INVALID_ADDRESS on failure.
+ lldb::addr_t
+ GetEntryPoint();
+
+ /// Checks to see if the target module has changed, updates the target
+ /// accordingly and returns the target executable module.
+ lldb::ModuleSP
+ GetTargetExecutable();
+
+ /// return the address of the Rendezvous breakpoint
+ lldb::addr_t
+ FindRendezvousBreakpointAddress( );
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(DynamicLoaderHexagonDYLD);
+
+ const lldb_private::SectionList *
+ GetSectionListFromModule(const lldb::ModuleSP module) const;
+};
+
+#endif // liblldb_DynamicLoaderHexagonDYLD_H_
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp
new file mode 100644
index 000000000000..5035e9d8bb17
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp
@@ -0,0 +1,403 @@
+//===-- HexagonDYLDRendezvous.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
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "HexagonDYLDRendezvous.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+/// Locates the address of the rendezvous structure. Returns the address on
+/// success and LLDB_INVALID_ADDRESS on failure.
+static addr_t
+ResolveRendezvousAddress(Process *process)
+{
+ addr_t info_location;
+ addr_t info_addr;
+ Error error;
+
+ info_location = process->GetImageInfoAddress();
+
+ if (info_location == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ info_addr = process->ReadPointerFromMemory(info_location, error);
+ if (error.Fail())
+ return LLDB_INVALID_ADDRESS;
+
+ if (info_addr == 0)
+ return LLDB_INVALID_ADDRESS;
+
+ return info_addr;
+}
+
+HexagonDYLDRendezvous::HexagonDYLDRendezvous(Process *process)
+ : m_process(process),
+ m_rendezvous_addr(LLDB_INVALID_ADDRESS),
+ m_current(),
+ m_previous(),
+ m_soentries(),
+ m_added_soentries(),
+ m_removed_soentries()
+{
+ m_thread_info.valid = false;
+
+ // Cache a copy of the executable path
+ if (m_process)
+ {
+ Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
+ if (exe_mod)
+ exe_mod->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
+ }
+}
+
+bool
+HexagonDYLDRendezvous::Resolve()
+{
+ const size_t word_size = 4;
+ Rendezvous info;
+ size_t address_size;
+ size_t padding;
+ addr_t info_addr;
+ addr_t cursor;
+
+ address_size = m_process->GetAddressByteSize();
+ padding = address_size - word_size;
+
+ if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
+ cursor = info_addr = ResolveRendezvousAddress(m_process);
+ else
+ cursor = info_addr = m_rendezvous_addr;
+
+ if (cursor == LLDB_INVALID_ADDRESS)
+ return false;
+
+ if (!(cursor = ReadWord(cursor, &info.version, word_size)))
+ return false;
+
+ if (!(cursor = ReadPointer(cursor + padding, &info.map_addr)))
+ return false;
+
+ if (!(cursor = ReadPointer(cursor, &info.brk)))
+ return false;
+
+ if (!(cursor = ReadWord(cursor, &info.state, word_size)))
+ return false;
+
+ if (!(cursor = ReadPointer(cursor + padding, &info.ldbase)))
+ return false;
+
+ // The rendezvous was successfully read. Update our internal state.
+ m_rendezvous_addr = info_addr;
+ m_previous = m_current;
+ m_current = info;
+
+ return UpdateSOEntries();
+}
+
+void
+HexagonDYLDRendezvous::SetRendezvousAddress( lldb::addr_t addr )
+{
+ m_rendezvous_addr = addr;
+}
+
+bool
+HexagonDYLDRendezvous::IsValid()
+{
+ return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
+}
+
+bool
+HexagonDYLDRendezvous::UpdateSOEntries()
+{
+ SOEntry entry;
+
+ if (m_current.map_addr == 0)
+ return false;
+
+ // When the previous and current states are consistent this is the first
+ // time we have been asked to update. Just take a snapshot of the currently
+ // loaded modules.
+ if (m_previous.state == eConsistent && m_current.state == eConsistent)
+ return TakeSnapshot(m_soentries);
+
+ // If we are about to add or remove a shared object clear out the current
+ // state and take a snapshot of the currently loaded images.
+ if (m_current.state == eAdd || m_current.state == eDelete)
+ {
+ // this is a fudge so that we can clear the assert below.
+ m_previous.state = eConsistent;
+ // We hit this assert on the 2nd run of this function after running the calc example
+ assert(m_previous.state == eConsistent);
+ m_soentries.clear();
+ m_added_soentries.clear();
+ m_removed_soentries.clear();
+ return TakeSnapshot(m_soentries);
+ }
+ assert(m_current.state == eConsistent);
+
+ // Otherwise check the previous state to determine what to expect and update
+ // accordingly.
+ if (m_previous.state == eAdd)
+ return UpdateSOEntriesForAddition();
+ else if (m_previous.state == eDelete)
+ return UpdateSOEntriesForDeletion();
+
+ return false;
+}
+
+bool
+HexagonDYLDRendezvous::UpdateSOEntriesForAddition()
+{
+ SOEntry entry;
+ iterator pos;
+
+ assert(m_previous.state == eAdd);
+
+ if (m_current.map_addr == 0)
+ return false;
+
+ for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
+ {
+ if (!ReadSOEntryFromMemory(cursor, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ // On Linux this is indicated by an empty path in the entry.
+ // On FreeBSD it is the name of the executable.
+ if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
+ continue;
+
+ pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
+ if (pos == m_soentries.end())
+ {
+ m_soentries.push_back(entry);
+ m_added_soentries.push_back(entry);
+ }
+ }
+
+ return true;
+}
+
+bool
+HexagonDYLDRendezvous::UpdateSOEntriesForDeletion()
+{
+ SOEntryList entry_list;
+ iterator pos;
+
+ assert(m_previous.state == eDelete);
+
+ if (!TakeSnapshot(entry_list))
+ return false;
+
+ for (iterator I = begin(); I != end(); ++I)
+ {
+ pos = std::find(entry_list.begin(), entry_list.end(), *I);
+ if (pos == entry_list.end())
+ m_removed_soentries.push_back(*I);
+ }
+
+ m_soentries = entry_list;
+ return true;
+}
+
+bool
+HexagonDYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
+{
+ SOEntry entry;
+
+ if (m_current.map_addr == 0)
+ return false;
+
+ for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
+ {
+ if (!ReadSOEntryFromMemory(cursor, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ // On Linux this is indicated by an empty path in the entry.
+ // On FreeBSD it is the name of the executable.
+ if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
+ continue;
+
+ entry_list.push_back(entry);
+ }
+
+ return true;
+}
+
+addr_t
+HexagonDYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size)
+{
+ Error error;
+
+ *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error);
+ if (error.Fail())
+ return 0;
+
+ return addr + size;
+}
+
+addr_t
+HexagonDYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst)
+{
+ Error error;
+
+ *dst = m_process->ReadPointerFromMemory(addr, error);
+ if (error.Fail())
+ return 0;
+
+ return addr + m_process->GetAddressByteSize();
+}
+
+std::string
+HexagonDYLDRendezvous::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++;
+ }
+ }
+
+ return str;
+}
+
+bool
+HexagonDYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
+{
+ entry.clear();
+ entry.link_addr = addr;
+
+ if (!(addr = ReadPointer(addr, &entry.base_addr)))
+ return false;
+
+ if (!(addr = ReadPointer(addr, &entry.path_addr)))
+ return false;
+
+ if (!(addr = ReadPointer(addr, &entry.dyn_addr)))
+ return false;
+
+ if (!(addr = ReadPointer(addr, &entry.next)))
+ return false;
+
+ if (!(addr = ReadPointer(addr, &entry.prev)))
+ return false;
+
+ entry.path = ReadStringFromMemory(entry.path_addr);
+
+ return true;
+}
+
+bool
+HexagonDYLDRendezvous::FindMetadata(const char *name, PThreadField field, uint32_t& value)
+{
+ Target& target = m_process->GetTarget();
+
+ SymbolContextList list;
+ if (!target.GetImages().FindSymbolsWithNameAndType (ConstString(name), eSymbolTypeAny, list))
+ return false;
+
+ Address address = list[0].symbol->GetAddress();
+ addr_t addr = address.GetLoadAddress (&target);
+ if (addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ Error error;
+ value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory(addr + field*sizeof(uint32_t), sizeof(uint32_t), 0, error);
+ if (error.Fail())
+ return false;
+
+ if (field == eSize)
+ value /= 8; // convert bits to bytes
+
+ return true;
+}
+
+const HexagonDYLDRendezvous::ThreadInfo&
+HexagonDYLDRendezvous::GetThreadInfo()
+{
+ if (!m_thread_info.valid)
+ {
+ bool ok = true;
+
+ ok &= FindMetadata ("_thread_db_pthread_dtvp", eOffset, m_thread_info.dtv_offset);
+ ok &= FindMetadata ("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size);
+ ok &= FindMetadata ("_thread_db_link_map_l_tls_modid", eOffset, m_thread_info.modid_offset);
+ ok &= FindMetadata ("_thread_db_dtv_t_pointer_val", eOffset, m_thread_info.tls_offset);
+
+ if (ok)
+ m_thread_info.valid = true;
+ }
+
+ return m_thread_info;
+}
+
+void
+HexagonDYLDRendezvous::DumpToLog(Log *log) const
+{
+ int state = GetState();
+
+ if (!log)
+ return;
+
+ log->PutCString("HexagonDYLDRendezvous:");
+ log->Printf(" Address: %" PRIx64, GetRendezvousAddress());
+ log->Printf(" Version: %" PRIu64, GetVersion());
+ log->Printf(" Link : %" PRIx64, GetLinkMapAddress());
+ log->Printf(" Break : %" PRIx64, GetBreakAddress());
+ log->Printf(" LDBase : %" PRIx64, GetLDBase());
+ log->Printf(" State : %s",
+ (state == eConsistent) ? "consistent" :
+ (state == eAdd) ? "add" :
+ (state == eDelete) ? "delete" : "unknown");
+
+ iterator I = begin();
+ iterator E = end();
+
+ if (I != E)
+ log->PutCString("HexagonDYLDRendezvous SOEntries:");
+
+ for (int i = 1; I != E; ++I, ++i)
+ {
+ log->Printf("\n SOEntry [%d] %s", i, I->path.c_str());
+ log->Printf(" Base : %" PRIx64, I->base_addr);
+ log->Printf(" Path : %" PRIx64, I->path_addr);
+ log->Printf(" Dyn : %" PRIx64, I->dyn_addr);
+ log->Printf(" Next : %" PRIx64, I->next);
+ log->Printf(" Prev : %" PRIx64, I->prev);
+ }
+}
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
new file mode 100644
index 000000000000..cd5121330457
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
@@ -0,0 +1,279 @@
+//===-- HexagonDYLDRendezvous.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_HexagonDYLDRendezvous_H_
+#define liblldb_HexagonDYLDRendezvous_H_
+
+// C Includes
+// C++ Includes
+#include <list>
+#include <string>
+
+// Other libraries and framework includes
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private
+{
+ class Process;
+}
+
+/// @class HexagonDYLDRendezvous
+/// @brief Interface to the runtime linker.
+///
+/// A structure is present in a processes memory space which is updated by the
+/// runtime liker each time a module is loaded or unloaded. This class provides
+/// an interface to this structure and maintains a consistent snapshot of the
+/// currently loaded modules.
+class HexagonDYLDRendezvous
+{
+
+ // This structure is used to hold the contents of the debug rendezvous
+ // information (struct r_debug) as found in the inferiors memory. Note that
+ // the layout of this struct is not binary compatible, it is simply large
+ // enough to hold the information on both 32 and 64 bit platforms.
+ struct Rendezvous {
+ uint64_t version;
+ lldb::addr_t map_addr;
+ lldb::addr_t brk;
+ uint64_t state;
+ lldb::addr_t ldbase;
+
+ Rendezvous()
+ : version (0)
+ , map_addr(LLDB_INVALID_ADDRESS)
+ , brk (LLDB_INVALID_ADDRESS)
+ , state (0)
+ , ldbase (0)
+ { }
+
+ };
+
+public:
+ // Various metadata supplied by the inferior's threading library to describe
+ // the per-thread state.
+ struct ThreadInfo {
+ bool valid; // whether we read valid metadata
+ uint32_t dtv_offset; // offset of DTV pointer within pthread
+ uint32_t dtv_slot_size; // size of one DTV slot
+ uint32_t modid_offset; // offset of module ID within link_map
+ uint32_t tls_offset; // offset of TLS pointer within DTV slot
+ };
+
+ HexagonDYLDRendezvous(lldb_private::Process *process);
+
+ /// Update the internal snapshot of runtime linker rendezvous and recompute
+ /// the currently loaded modules.
+ ///
+ /// This method should be called once one start up, then once each time the
+ /// runtime linker enters the function given by GetBreakAddress().
+ ///
+ /// @returns true on success and false on failure.
+ ///
+ /// @see GetBreakAddress().
+ bool
+ Resolve();
+
+ /// @returns true if this rendezvous has been located in the inferiors
+ /// address space and false otherwise.
+ bool
+ IsValid();
+
+ /// @returns the address of the rendezvous structure in the inferiors
+ /// address space.
+ lldb::addr_t
+ GetRendezvousAddress() const { return m_rendezvous_addr; }
+
+ /// Provide the dyld structure address
+ void
+ SetRendezvousAddress( lldb::addr_t );
+
+ /// @returns the version of the rendezvous protocol being used.
+ uint64_t
+ GetVersion() const { return m_current.version; }
+
+ /// @returns address in the inferiors address space containing the linked
+ /// list of shared object descriptors.
+ lldb::addr_t
+ GetLinkMapAddress() const { return m_current.map_addr; }
+
+ /// A breakpoint should be set at this address and Resolve called on each
+ /// hit.
+ ///
+ /// @returns the address of a function called by the runtime linker each
+ /// time a module is loaded/unloaded, or about to be loaded/unloaded.
+ ///
+ /// @see Resolve()
+ lldb::addr_t
+ GetBreakAddress() const { return m_current.brk; }
+
+ /// In hexagon it is possible that we can know the dyld breakpoint without
+ /// having to find it from the rendezvous structure
+ ///
+ void
+ SetBreakAddress( lldb::addr_t addr ) { m_current.brk = addr; }
+
+ /// Returns the current state of the rendezvous structure.
+ uint64_t
+ GetState() const { return m_current.state; }
+
+ /// @returns the base address of the runtime linker in the inferiors address
+ /// space.
+ lldb::addr_t
+ GetLDBase() const { return m_current.ldbase; }
+
+ /// @returns the thread layout metadata from the inferiors thread library.
+ const ThreadInfo&
+ GetThreadInfo();
+
+ /// @returns true if modules have been loaded into the inferior since the
+ /// last call to Resolve().
+ bool
+ ModulesDidLoad() const { return !m_added_soentries.empty(); }
+
+ /// @returns true if modules have been unloaded from the inferior since the
+ /// last call to Resolve().
+ bool
+ ModulesDidUnload() const { return !m_removed_soentries.empty(); }
+
+ void
+ DumpToLog(lldb_private::Log *log) const;
+
+ /// @brief Constants describing the state of the rendezvous.
+ ///
+ /// @see GetState().
+ enum RendezvousState
+ {
+ eConsistent = 0,
+ eAdd ,
+ eDelete ,
+ };
+
+ /// @brief Structure representing the shared objects currently loaded into
+ /// the inferior process.
+ ///
+ /// This object is a rough analogue to the struct link_map object which
+ /// actually lives in the inferiors memory.
+ struct SOEntry {
+ lldb::addr_t link_addr; ///< Address of this link_map.
+ lldb::addr_t base_addr; ///< Base address of the loaded object.
+ lldb::addr_t path_addr; ///< String naming the shared object.
+ lldb::addr_t dyn_addr; ///< Dynamic section of shared object.
+ lldb::addr_t next; ///< Address of next so_entry.
+ lldb::addr_t prev; ///< Address of previous so_entry.
+ std::string path; ///< File name of shared object.
+
+ SOEntry() { clear(); }
+
+ bool operator ==(const SOEntry &entry) {
+ return this->path == entry.path;
+ }
+
+ void clear() {
+ link_addr = 0;
+ base_addr = 0;
+ path_addr = 0;
+ dyn_addr = 0;
+ next = 0;
+ prev = 0;
+ path.clear();
+ }
+ };
+
+protected:
+ typedef std::list<SOEntry> SOEntryList;
+
+public:
+ typedef SOEntryList::const_iterator iterator;
+
+ /// Iterators over all currently loaded modules.
+ iterator begin() const { return m_soentries.begin(); }
+ iterator end() const { return m_soentries.end(); }
+
+ /// Iterators over all modules loaded into the inferior since the last call
+ /// to Resolve().
+ iterator loaded_begin() const { return m_added_soentries.begin(); }
+ iterator loaded_end() const { return m_added_soentries.end(); }
+
+ /// Iterators over all modules unloaded from the inferior since the last
+ /// call to Resolve().
+ iterator unloaded_begin() const { return m_removed_soentries.begin(); }
+ iterator unloaded_end() const { return m_removed_soentries.end(); }
+
+protected:
+ lldb_private::Process *m_process;
+
+ // Cached copy of executable pathname
+ char m_exe_path[PATH_MAX];
+
+ /// Location of the r_debug structure in the inferiors address space.
+ lldb::addr_t m_rendezvous_addr;
+
+ /// Current and previous snapshots of the rendezvous structure.
+ Rendezvous m_current;
+ Rendezvous m_previous;
+
+ /// List of SOEntry objects corresponding to the current link map state.
+ SOEntryList m_soentries;
+
+ /// List of SOEntry's added to the link map since the last call to Resolve().
+ SOEntryList m_added_soentries;
+
+ /// List of SOEntry's removed from the link map since the last call to
+ /// Resolve().
+ SOEntryList m_removed_soentries;
+
+ /// Threading metadata read from the inferior.
+ ThreadInfo m_thread_info;
+
+ /// Reads an unsigned integer of @p size bytes from the inferior's address
+ /// space starting at @p addr.
+ ///
+ /// @returns addr + size if the read was successful and false otherwise.
+ lldb::addr_t
+ ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size);
+
+ /// Reads an address from the inferior's address space starting at @p addr.
+ ///
+ /// @returns addr + target address size if the read was successful and
+ /// 0 otherwise.
+ lldb::addr_t
+ ReadPointer(lldb::addr_t addr, lldb::addr_t *dst);
+
+ /// Reads a null-terminated C string from the memory location starting at @p
+ /// addr.
+ std::string
+ ReadStringFromMemory(lldb::addr_t addr);
+
+ /// Reads an SOEntry starting at @p addr.
+ bool
+ ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
+
+ /// Updates the current set of SOEntries, the set of added entries, and the
+ /// set of removed entries.
+ bool
+ UpdateSOEntries();
+
+ bool
+ UpdateSOEntriesForAddition();
+
+ bool
+ UpdateSOEntriesForDeletion();
+
+ /// Reads the current list of shared objects according to the link map
+ /// supplied by the runtime linker.
+ bool
+ TakeSnapshot(SOEntryList &entry_list);
+
+ enum PThreadField { eSize, eNElem, eOffset };
+
+ bool FindMetadata(const char *name, PThreadField field, uint32_t& value);
+};
+
+#endif // liblldb_HexagonDYLDRendezvous_H_
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
index c079d0fc381f..04a6792fbf01 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
@@ -57,11 +57,10 @@ ParseAuxvEntry(DataExtractor &data,
DataBufferSP
AuxVector::GetAuxvData()
{
-#if defined(__linux__) || defined(__FreeBSD__)
- if (m_process->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return static_cast<ProcessElfCore *>(m_process)->GetAuxvData();
-#endif
- return lldb_private::Host::GetAuxvData(m_process);
+ if (m_process)
+ return m_process->GetAuxvData ();
+ else
+ return DataBufferSP ();
}
void
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index 3c5dcc5222af..0e203fe43a79 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -14,6 +14,7 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
+#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -28,21 +29,61 @@ using namespace lldb_private;
static addr_t
ResolveRendezvousAddress(Process *process)
{
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
addr_t info_location;
addr_t info_addr;
Error error;
+ // 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();
+ if (log)
+ log->Printf ("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location);
+ // 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;
+ if (target)
+ {
+ ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
+ Address addr = obj_file->GetImageInfoAddress(target);
+
+ if (addr.IsValid())
+ {
+ info_location = addr.GetLoadAddress(target);
+ if (log)
+ log->Printf ("%s resolved via direct object file approach to 0x%" PRIx64, __FUNCTION__, info_location);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("%s FAILED - direct object file approach did not yield a valid address", __FUNCTION__);
+ }
+ }
+ }
+
+ if (info_location == LLDB_INVALID_ADDRESS)
+ {
+ if (log)
+ log->Printf ("%s FAILED - invalid info address", __FUNCTION__);
return LLDB_INVALID_ADDRESS;
+ }
info_addr = process->ReadPointerFromMemory(info_location, error);
if (error.Fail())
+ {
+ if (log)
+ log->Printf ("%s FAILED - could not read from the info location: %s", __FUNCTION__, error.AsCString ());
return LLDB_INVALID_ADDRESS;
+ }
if (info_addr == 0)
+ {
+ if (log)
+ log->Printf ("%s FAILED - the rendezvous address contained at 0x%" PRIx64 " returned a null value", __FUNCTION__, info_location);
return LLDB_INVALID_ADDRESS;
+ }
return info_addr;
}
@@ -56,6 +97,8 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
m_added_soentries(),
m_removed_soentries()
{
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
m_thread_info.valid = false;
// Cache a copy of the executable path
@@ -63,13 +106,24 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
{
Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
if (exe_mod)
+ {
exe_mod->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
+ if (log)
+ log->Printf ("DYLDRendezvous::%s exe module executable path set: '%s'", __FUNCTION__, m_exe_path);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("DYLDRendezvous::%s cannot cache exe module path: null executable module pointer", __FUNCTION__);
+ }
}
}
bool
DYLDRendezvous::Resolve()
{
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
const size_t word_size = 4;
Rendezvous info;
size_t address_size;
@@ -79,12 +133,16 @@ DYLDRendezvous::Resolve()
address_size = m_process->GetAddressByteSize();
padding = address_size - word_size;
+ if (log)
+ log->Printf ("DYLDRendezvous::%s address size: %zu, padding %zu", __FUNCTION__, address_size, padding);
if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
cursor = info_addr = ResolveRendezvousAddress(m_process);
else
cursor = info_addr = m_rendezvous_addr;
-
+ if (log)
+ log->Printf ("DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__, cursor);
+
if (cursor == LLDB_INVALID_ADDRESS)
return false;
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 286b1ef62d9a..549e5f9b5345 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -468,7 +468,7 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const l
if (modid == -1)
return LLDB_INVALID_ADDRESS;
- // Lookup the DTV stucture for this thread.
+ // Lookup the DTV structure for this thread.
addr_t dtv_ptr = tp + metadata.dtv_offset;
addr_t dtv = ReadPointer (dtv_ptr);
if (dtv == LLDB_INVALID_ADDRESS)
diff --git a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
index a99435fa32ad..ea33164cf823 100644
--- a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
+++ b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
@@ -17,7 +17,6 @@
#include <string>
// Other libraries and framework includes
-#include "llvm/Support/MachO.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Host/FileSpec.h"
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index f1cb41d5a913..fa8681ed69fe 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -24,6 +24,7 @@
#include "Plugins/Process/Utility/ARMUtils.h"
#include "Utility/ARM_DWARF_Registers.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
// and countTrailingZeros function
@@ -266,7 +267,7 @@ EmulateInstructionARM::WriteBits32Unknown (int n)
}
bool
-EmulateInstructionARM::GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo &reg_info)
+EmulateInstructionARM::GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &reg_info)
{
if (reg_kind == eRegisterKindGeneric)
{
@@ -2169,7 +2170,7 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc
addr_t sp_offset = imm32;
addr_t addr = sp;
uint32_t i;
- uint64_t data; // uint64_t to accomodate 64-bit registers.
+ uint64_t data; // uint64_t to accommodate 64-bit registers.
EmulateInstruction::Context context;
if (conditional)
@@ -3626,7 +3627,7 @@ EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding en
}
// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
-// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
+// consecutive memory locations end just below this address, and the address of the lowest of those locations can
// be optionally written back to the base register.
bool
EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
@@ -4033,7 +4034,7 @@ EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncodi
}
// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
-// from a base register. The consecutive memory locations start at this address, and teh address just above the last
+// from a base register. The consecutive memory locations start at this address, and the address just above the last
// of those locations can optionally be written back to the base register.
bool
EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
@@ -4588,7 +4589,7 @@ EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding en
return true;
}
-// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
+// STR (store immediate) calculates an address from a base register value and an immediate offset, and stores a word
// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
bool
EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
@@ -5076,7 +5077,7 @@ EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncodin
}
// STRH (register) calculates an address from a base register value and an offset register value, and stores a
-// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
+// halfword from a register to memory. The offset register value can be shifted left by 0, 1, 2, or 3 bits.
bool
EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
{
@@ -5941,7 +5942,7 @@ EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARME
}
// LDR (register) calculates an address from a base register value and an offset register value, loads a word
-// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
+// from memory, and writes it to a register. The offset register value can optionally be shifted.
bool
EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
{
@@ -11033,7 +11034,7 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc
}
// A8.6.320
-// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
+// This instruction loads a single extension register from memory, using an address from an ARM core register, with
// an optional offset.
bool
EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
@@ -11638,7 +11639,7 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi
}
// A8.6.391 VST1 (multiple single elements)
-// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
+// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four registers, without
// interleaving. Every element of each register is stored.
bool
EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
@@ -12506,7 +12507,7 @@ EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32
{ 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
};
- static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
+ static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_arm_opcodes);
for (size_t i=0; i<k_num_arm_opcodes; ++i)
{
@@ -12832,7 +12833,7 @@ EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint
{ 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
};
- const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
+ const size_t k_num_thumb_opcodes = llvm::array_lengthof(g_thumb_opcodes);
for (size_t i=0; i<k_num_thumb_opcodes; ++i)
{
if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
@@ -13019,7 +13020,7 @@ EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditio
break;
case 7:
// Always execute (cond == 0b1110, or the special 0b1111 which gives
- // opcodes different meanings, but always means execution happpens.
+ // opcodes different meanings, but always means execution happens.
if (is_conditional)
*is_conditional = false;
result = true;
@@ -13307,7 +13308,8 @@ EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
uint32_t
EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
{
- uint32_t reg_kind, reg_num;
+ lldb::RegisterKind reg_kind;
+ uint32_t reg_num;
switch (num)
{
case SP_REG:
@@ -13388,7 +13390,8 @@ EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
}
else
{
- uint32_t reg_kind, reg_num;
+ lldb::RegisterKind reg_kind;
+ uint32_t reg_num;
switch (Rd)
{
case SP_REG:
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index 81e78847a1f3..d107ca6bc702 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -170,7 +170,7 @@ public:
TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data);
virtual bool
- GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo &reg_info);
+ GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &reg_info);
virtual bool
diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
new file mode 100644
index 000000000000..3900af9b00d0
--- /dev/null
+++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
@@ -0,0 +1,719 @@
+//===-- EmulateInstructionARM64.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EmulateInstructionARM64.h"
+
+#include <stdlib.h>
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/UnwindPlan.h"
+
+#include "Plugins/Process/Utility/ARMDefines.h"
+#include "Plugins/Process/Utility/ARMUtils.h"
+#include "Utility/ARM64_DWARF_Registers.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
+ // and CountTrailingZeros_32 function
+
+#include "Plugins/Process/Utility/InstructionUtils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define No_VFP 0
+#define VFPv1 (1u << 1)
+#define VFPv2 (1u << 2)
+#define VFPv3 (1u << 3)
+#define AdvancedSIMD (1u << 4)
+
+#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
+#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
+#define VFPv2v3 (VFPv2 | VFPv3)
+
+#define UInt(x) ((uint64_t)x)
+#define SInt(x) ((int64_t)x)
+#define bit bool
+#define boolean bool
+#define integer int64_t
+
+static inline bool
+IsZero(uint64_t x)
+{
+ return x == 0;
+}
+
+static inline uint64_t
+NOT(uint64_t x)
+{
+ return ~x;
+}
+
+#if 0
+// LSL_C()
+// =======
+static inline uint64_t
+LSL_C (uint64_t x, integer shift, bool &carry_out)
+{
+ assert (shift >= 0);
+ uint64_t result = x << shift;
+ carry_out = ((1ull << (64-1)) >> (shift - 1)) != 0;
+ return result;
+}
+#endif
+
+// LSL()
+// =====
+
+static inline uint64_t
+LSL(uint64_t x, integer shift)
+{
+ if (shift == 0)
+ return x;
+ return x << shift;
+}
+
+// AddWithCarry()
+// ===============
+static inline uint64_t
+AddWithCarry (uint32_t N, uint64_t x, uint64_t y, bit carry_in, EmulateInstructionARM64::ProcState &proc_state)
+{
+ uint64_t unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in);
+ int64_t signed_sum = SInt(x) + SInt(y) + UInt(carry_in);
+ uint64_t result = unsigned_sum;
+ if (N < 64)
+ result = Bits64 (result, N-1, 0);
+ proc_state.N = Bit64(result, N-1);
+ proc_state.Z = IsZero(result);
+ proc_state.C = UInt(result) == unsigned_sum;
+ proc_state.V = SInt(result) == signed_sum;
+ return result;
+}
+
+// ConstrainUnpredictable()
+// ========================
+
+EmulateInstructionARM64::ConstraintType
+ConstrainUnpredictable (EmulateInstructionARM64::Unpredictable which)
+{
+ EmulateInstructionARM64::ConstraintType result = EmulateInstructionARM64::Constraint_UNKNOWN;
+ switch (which)
+ {
+ case EmulateInstructionARM64::Unpredictable_WBOVERLAP:
+ case EmulateInstructionARM64::Unpredictable_LDPOVERLAP:
+ // TODO: don't know what to really do here? Pseudo code says:
+ // set result to one of above Constraint behaviours or UNDEFINED
+ break;
+ }
+ return result;
+}
+
+
+
+//----------------------------------------------------------------------
+//
+// EmulateInstructionARM implementation
+//
+//----------------------------------------------------------------------
+
+void
+EmulateInstructionARM64::Initialize ()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic (),
+ GetPluginDescriptionStatic (),
+ CreateInstance);
+}
+
+void
+EmulateInstructionARM64::Terminate ()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+ConstString
+EmulateInstructionARM64::GetPluginNameStatic ()
+{
+ ConstString g_plugin_name ("lldb.emulate-instruction.arm64");
+ return g_plugin_name;
+}
+
+lldb_private::ConstString
+EmulateInstructionARM64::GetPluginName()
+{
+ static ConstString g_plugin_name ("EmulateInstructionARM64");
+ return g_plugin_name;
+}
+
+const char *
+EmulateInstructionARM64::GetPluginDescriptionStatic ()
+{
+ return "Emulate instructions for the ARM64 architecture.";
+}
+
+EmulateInstruction *
+EmulateInstructionARM64::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
+{
+ if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic(inst_type))
+ {
+ if (arch.GetTriple().getArch() == llvm::Triple::aarch64)
+ {
+ std::auto_ptr<EmulateInstructionARM64> emulate_insn_ap (new EmulateInstructionARM64 (arch));
+ if (emulate_insn_ap.get())
+ return emulate_insn_ap.release();
+ }
+ }
+
+ return NULL;
+}
+
+bool
+EmulateInstructionARM64::SetTargetTriple (const ArchSpec &arch)
+{
+ if (arch.GetTriple().getArch () == llvm::Triple::arm)
+ return true;
+ else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
+ return true;
+
+ return false;
+}
+
+bool
+EmulateInstructionARM64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &reg_info)
+{
+ if (reg_kind == eRegisterKindGeneric)
+ {
+ switch (reg_num)
+ {
+ case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::pc; break;
+ case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::sp; break;
+ case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::fp; break;
+ case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::lr; break;
+ case LLDB_REGNUM_GENERIC_FLAGS:
+ // There is no DWARF register number for the CPSR right now...
+ reg_info.name = "cpsr";
+ reg_info.alt_name = NULL;
+ reg_info.byte_size = 4;
+ reg_info.byte_offset = 0;
+ reg_info.encoding = eEncodingUint;
+ reg_info.format = eFormatHex;
+ for (uint32_t i=0; i<lldb::kNumRegisterKinds; ++i)
+ reg_info.kinds[reg_kind] = LLDB_INVALID_REGNUM;
+ reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
+ return true;
+
+ default: return false;
+ }
+ }
+
+ if (reg_kind == eRegisterKindDWARF)
+ return arm64_dwarf::GetRegisterInfo(reg_num, reg_info);
+ return false;
+}
+
+EmulateInstructionARM64::Opcode*
+EmulateInstructionARM64::GetOpcodeForInstruction (const uint32_t opcode)
+{
+ static EmulateInstructionARM64::Opcode
+ g_opcodes[] =
+ {
+ //----------------------------------------------------------------------
+ // Prologue instructions
+ //----------------------------------------------------------------------
+
+ // push register(s)
+ { 0xff000000, 0xd1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0xf1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS <Xd>, <Xn|SP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS <Xd>, <Xn|SP>, #<imm> {, <shift>}" },
+
+
+ { 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" },
+
+ { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" },
+
+ { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+
+ };
+ static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_opcodes);
+
+ for (size_t i=0; i<k_num_arm_opcodes; ++i)
+ {
+ if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value)
+ return &g_opcodes[i];
+ }
+ return NULL;
+}
+
+bool
+EmulateInstructionARM64::ReadInstruction ()
+{
+ bool success = false;
+ m_addr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
+ if (success)
+ {
+ Context read_inst_context;
+ read_inst_context.type = eContextReadOpcode;
+ read_inst_context.SetNoArgs ();
+ m_opcode.SetOpcode32 (ReadMemoryUnsigned (read_inst_context, m_addr, 4, 0, &success), GetByteOrder());
+ }
+ if (!success)
+ m_addr = LLDB_INVALID_ADDRESS;
+ return success;
+}
+
+
+bool
+EmulateInstructionARM64::EvaluateInstruction (uint32_t evaluate_options)
+{
+ const uint32_t opcode = m_opcode.GetOpcode32();
+ Opcode *opcode_data = GetOpcodeForInstruction(opcode);
+ if (opcode_data == NULL)
+ return false;
+
+ //printf ("opcode template for 0x%8.8x: %s\n", opcode, opcode_data->name);
+ const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
+ m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
+
+ bool success = false;
+// if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
+// {
+// m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, // use eRegisterKindDWARF is we ever get a cpsr DWARF register number
+// LLDB_REGNUM_GENERIC_FLAGS, // use arm64_dwarf::cpsr if we ever get one
+// 0,
+// &success);
+// }
+
+ // Only return false if we are unable to read the CPSR if we care about conditions
+ if (success == false && m_ignore_conditions == false)
+ return false;
+
+ uint32_t orig_pc_value = 0;
+ if (auto_advance_pc)
+ {
+ orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::pc, 0, &success);
+ if (!success)
+ return false;
+ }
+
+ // Call the Emulate... function.
+ success = (this->*opcode_data->callback) (opcode);
+ if (!success)
+ return false;
+
+ if (auto_advance_pc)
+ {
+ uint32_t new_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::pc, 0, &success);
+ if (!success)
+ return false;
+
+ if (auto_advance_pc && (new_pc_value == orig_pc_value))
+ {
+ EmulateInstruction::Context context;
+ context.type = eContextAdvancePC;
+ context.SetNoArgs();
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::pc, orig_pc_value + 4))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+EmulateInstructionARM64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+ const bool can_replace = false;
+
+ // Our previous Call Frame Address is the stack pointer
+ row->SetCFARegister (arm64_dwarf::sp);
+
+ // Our previous PC is in the LR
+ row->SetRegisterLocationToRegister(arm64_dwarf::pc, arm64_dwarf::lr, can_replace);
+
+ unwind_plan.AppendRow (row);
+
+ // All other registers are the same.
+
+ unwind_plan.SetSourceName ("EmulateInstructionARM64");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
+ return true;
+}
+
+
+
+bool
+EmulateInstructionARM64::Emulate_addsub_imm (const uint32_t opcode)
+{
+ // integer d = UInt(Rd);
+ // integer n = UInt(Rn);
+ // integer datasize = if sf == 1 then 64 else 32;
+ // boolean sub_op = (op == 1);
+ // boolean setflags = (S == 1);
+ // bits(datasize) imm;
+ //
+ // case shift of
+ // when '00' imm = ZeroExtend(imm12, datasize);
+ // when '01' imm = ZeroExtend(imm12 : Zeros(12), datasize);
+ // when '1x' UNDEFINED;
+ //
+ //
+ // bits(datasize) result;
+ // bits(datasize) operand1 = if n == 31 then SP[] else X[n];
+ // bits(datasize) operand2 = imm;
+ // bits(4) nzcv;
+ // bit carry_in;
+ //
+ // if sub_op then
+ // operand2 = NOT(operand2);
+ // carry_in = 1;
+ // else
+ // carry_in = 0;
+ //
+ // (result, nzcv) = AddWithCarry(operand1, operand2, carry_in);
+ //
+ // if setflags then
+ // PSTATE.NZCV = nzcv;
+ //
+ // if d == 31 && !setflags then
+ // SP[] = result;
+ // else
+ // X[d] = result;
+
+ const uint32_t sf = Bit32(opcode, 31);
+ const uint32_t op = Bit32(opcode, 30);
+ const uint32_t S = Bit32(opcode, 29);
+ const uint32_t shift = Bits32(opcode, 23, 22);
+ const uint32_t imm12 = Bits32(opcode, 21, 10);
+ const uint32_t Rn = Bits32(opcode, 9, 5);
+ const uint32_t Rd = Bits32(opcode, 4, 0);
+
+ bool success = false;
+
+ const uint32_t d = UInt(Rd);
+ const uint32_t n = UInt(Rn);
+ const uint32_t datasize = (sf == 1) ? 64 : 32;
+ boolean sub_op = op == 1;
+ boolean setflags = S == 1;
+ uint64_t imm;
+
+ switch (shift)
+ {
+ case 0: imm = imm12; break;
+ case 1: imm = imm12 << 12; break;
+ default: return false; // UNDEFINED;
+ }
+ uint64_t result;
+ uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success);
+ uint64_t operand2 = imm;
+ bit carry_in;
+
+ if (sub_op)
+ {
+ operand2 = NOT(operand2);
+ carry_in = 1;
+ imm = -imm; // For the Register plug offset context below
+ }
+ else
+ {
+ carry_in = 0;
+ }
+
+ ProcState proc_state;
+
+ result = AddWithCarry (datasize, operand1, operand2, carry_in, proc_state);
+
+ if (setflags)
+ {
+ m_emulated_pstate.N = proc_state.N;
+ m_emulated_pstate.Z = proc_state.Z;
+ m_emulated_pstate.C = proc_state.C;
+ m_emulated_pstate.V = proc_state.V;
+ }
+
+ Context context;
+ RegisterInfo reg_info_Rn;
+ if (arm64_dwarf::GetRegisterInfo (n, reg_info_Rn))
+ context.SetRegisterPlusOffset (reg_info_Rn, imm);
+
+ if ((n == arm64_dwarf::sp || n == arm64_dwarf::fp) &&
+ d == arm64_dwarf::sp &&
+ !setflags)
+ {
+ context.type = EmulateInstruction::eContextAdjustStackPointer;
+ }
+ else if (d == arm64_dwarf::fp &&
+ n == arm64_dwarf::sp &&
+ !setflags)
+ {
+ context.type = EmulateInstruction::eContextSetFramePointer;
+ }
+ else
+ {
+ context.type = EmulateInstruction::eContextImmediate;
+ }
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::x0 + d, result);
+
+ return false;
+}
+
+bool
+EmulateInstructionARM64::Emulate_ldstpair_off (const uint32_t opcode)
+{
+ return Emulate_ldstpair (opcode, AddrMode_OFF);
+}
+
+
+bool
+EmulateInstructionARM64::Emulate_ldstpair_pre (const uint32_t opcode)
+{
+ return Emulate_ldstpair (opcode, AddrMode_PRE);
+}
+
+bool
+EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mode)
+{
+ uint32_t opc = Bits32(opcode, 31, 30);
+ uint32_t V = Bit32(opcode, 26);
+ uint32_t L = Bit32(opcode, 22);
+ uint32_t imm7 = Bits32(opcode, 21, 15);
+ uint32_t Rt2 = Bits32(opcode, 14, 10);
+ uint32_t Rn = Bits32(opcode, 9, 5);
+ uint32_t Rt = Bits32(opcode, 4, 0);
+
+ integer n = UInt(Rn);
+ integer t = UInt(Rt);
+ integer t2 = UInt(Rt2);
+ uint64_t idx;
+
+ MemOp memop = L == 1 ? MemOp_LOAD : MemOp_STORE;
+ boolean vector = (V == 1);
+ //AccType acctype = AccType_NORMAL;
+ boolean is_signed = false;
+ boolean wback = a_mode != AddrMode_OFF;
+ boolean wb_unknown = false;
+ boolean rt_unknown = false;
+ integer scale;
+ integer size;
+
+ if (opc == 3)
+ return false; // UNDEFINED
+
+ if (vector)
+ {
+ scale = 2 + UInt(opc);
+ }
+ else
+ {
+ scale = (opc & 2) ? 3 : 2;
+ is_signed = (opc & 1) != 0;
+ if (is_signed && memop == MemOp_STORE)
+ return false; // UNDEFINED
+ }
+
+ if (!vector && wback && ((t == n) || (t2 == n)))
+ {
+ switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP))
+ {
+ case Constraint_UNKNOWN:
+ wb_unknown = true; // writeback is UNKNOWN
+ break;
+
+ case Constraint_SUPPRESSWB:
+ wback = false; // writeback is suppressed
+ break;
+
+ case Constraint_NOP:
+ memop = MemOp_NOP; // do nothing
+ wback = false;
+ break;
+
+ case Constraint_NONE:
+ break;
+ }
+ }
+
+ if (memop == MemOp_LOAD && t == t2)
+ {
+ switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP))
+ {
+ case Constraint_UNKNOWN:
+ rt_unknown = true; // result is UNKNOWN
+ break;
+
+ case Constraint_NOP:
+ memop = MemOp_NOP; // do nothing
+ wback = false;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ idx = LSL(llvm::SignExtend64<7>(imm7), scale);
+ size = (integer)1 << scale;
+ uint64_t datasize = size * 8;
+ uint64_t address;
+ uint64_t wb_address;
+
+ RegisterValue data_Rt;
+ RegisterValue data_Rt2;
+
+ // if (vector)
+ // CheckFPEnabled(false);
+
+ RegisterInfo reg_info_base;
+ RegisterInfo reg_info_Rt;
+ RegisterInfo reg_info_Rt2;
+ if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base))
+ return false;
+
+ if (vector)
+ {
+ if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::v0 + n, reg_info_Rt))
+ return false;
+ if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::v0 + n, reg_info_Rt2))
+ return false;
+ }
+ else
+ {
+ if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt))
+ return false;
+ if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t2, reg_info_Rt2))
+ return false;
+ }
+
+ bool success = false;
+ if (n == 31)
+ {
+ //CheckSPAlignment();
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::sp, 0, &success);
+ }
+ else
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success);
+
+ wb_address = address + idx;
+ if (a_mode != AddrMode_POST)
+ address = wb_address;
+
+ Context context_t;
+ Context context_t2;
+
+ if (n == 31 || n == 29) // if this store is based off of the sp or fp register
+ {
+ context_t.type = eContextPushRegisterOnStack;
+ context_t2.type = eContextPushRegisterOnStack;
+ }
+ else
+ {
+ context_t.type = eContextRegisterPlusOffset;
+ context_t2.type = eContextRegisterPlusOffset;
+ }
+ context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0);
+ context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size);
+ uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
+ Error error;
+
+ switch (memop)
+ {
+ case MemOp_STORE:
+ {
+ if (!ReadRegister (&reg_info_Rt, data_Rt))
+ return false;
+
+ if (data_Rt.GetAsMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!WriteMemory(context_t, address + 0, buffer, reg_info_Rt.byte_size))
+ return false;
+
+ if (!ReadRegister (&reg_info_Rt2, data_Rt2))
+ return false;
+
+ if (data_Rt2.GetAsMemoryData(&reg_info_Rt2, buffer, reg_info_Rt2.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!WriteMemory(context_t2, address + size, buffer, reg_info_Rt2.byte_size))
+ return false;
+ }
+ break;
+
+ case MemOp_LOAD:
+ {
+ if (rt_unknown)
+ memset (buffer, 'U', reg_info_Rt.byte_size);
+ else
+ {
+ if (!ReadMemory (context_t, address, buffer, reg_info_Rt.byte_size))
+ return false;
+ }
+
+ if (data_Rt.SetFromMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!vector && is_signed && !data_Rt.SignExtend (datasize))
+ return false;
+
+ if (!WriteRegister (context_t, &reg_info_Rt, data_Rt))
+ return false;
+
+ if (!rt_unknown)
+ {
+ if (!ReadMemory (context_t2, address + size, buffer, reg_info_Rt2.byte_size))
+ return false;
+ }
+
+ if (data_Rt2.SetFromMemoryData(&reg_info_Rt2, buffer, reg_info_Rt2.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!vector && is_signed && !data_Rt2.SignExtend (datasize))
+ return false;
+
+ if (!WriteRegister (context_t2, &reg_info_Rt2, data_Rt2))
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (wback)
+ {
+ if (wb_unknown)
+ wb_address = LLDB_INVALID_ADDRESS;
+ Context context;
+ context.SetImmediateSigned (idx);
+ if (n == 31)
+ context.type = eContextAdjustStackPointer;
+ else
+ context.type = eContextAdjustBaseRegister;
+ WriteRegisterUnsigned (context, &reg_info_base, wb_address);
+ }
+ return true;
+}
diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
new file mode 100644
index 000000000000..7e18d09a0ee2
--- /dev/null
+++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
@@ -0,0 +1,297 @@
+//===-- EmulateInstructionARM64.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef EmulateInstructionARM64_h_
+#define EmulateInstructionARM64_h_
+
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Interpreter/OptionValue.h"
+#include "Plugins/Process/Utility/ARMDefines.h"
+
+class EmulateInstructionARM64 : public lldb_private::EmulateInstruction
+{
+public:
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic ();
+
+ static const char *
+ GetPluginDescriptionStatic ();
+
+ static lldb_private::EmulateInstruction *
+ CreateInstance (const lldb_private::ArchSpec &arch,
+ lldb_private::InstructionType inst_type);
+
+ static bool
+ SupportsEmulatingInstructionsOfTypeStatic (lldb_private::InstructionType inst_type)
+ {
+ switch (inst_type)
+ {
+ case lldb_private::eInstructionTypeAny:
+ case lldb_private::eInstructionTypePrologueEpilogue:
+ return true;
+
+ case lldb_private::eInstructionTypePCModifying:
+ case lldb_private::eInstructionTypeAll:
+ return false;
+ }
+ return false;
+ }
+
+ virtual lldb_private::ConstString
+ GetPluginName();
+
+ virtual lldb_private::ConstString
+ GetShortPluginName()
+ {
+ return GetPluginNameStatic();
+ }
+
+ virtual uint32_t
+ GetPluginVersion()
+ {
+ return 1;
+ }
+
+ bool
+ SetTargetTriple (const lldb_private::ArchSpec &arch);
+
+ EmulateInstructionARM64 (const lldb_private::ArchSpec &arch) :
+ EmulateInstruction (arch),
+ m_opcode_pstate (),
+ m_emulated_pstate (),
+ m_ignore_conditions (false)
+ {
+ }
+
+ virtual bool
+ SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type)
+ {
+ return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
+ }
+
+ virtual bool
+ ReadInstruction ();
+
+ virtual bool
+ EvaluateInstruction (uint32_t evaluate_options);
+
+ virtual bool
+ TestEmulation (lldb_private::Stream *out_stream,
+ lldb_private::ArchSpec &arch,
+ lldb_private::OptionValueDictionary *test_data)
+ {
+ return false;
+ }
+
+ virtual bool
+ GetRegisterInfo (lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ lldb_private::RegisterInfo &reg_info);
+
+ virtual bool
+ CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan);
+
+
+ typedef enum
+ {
+ AddrMode_OFF,
+ AddrMode_PRE,
+ AddrMode_POST
+ } AddrMode;
+
+ typedef enum
+ {
+ BranchType_CALL,
+ BranchType_ERET,
+ BranchType_DRET,
+ BranchType_RET,
+ BranchType_JMP
+ } BranchType;
+
+ typedef enum
+ {
+ CountOp_CLZ,
+ CountOp_CLS,
+ CountOp_CNT
+ } CountOp;
+
+ typedef enum
+ {
+ RevOp_RBIT,
+ RevOp_REV16,
+ RevOp_REV32,
+ RevOp_REV64
+ } RevOp;
+
+ typedef enum
+ {
+ BitwiseOp_NOT,
+ BitwiseOp_RBIT
+ } BitwiseOp;
+
+
+ typedef enum
+ {
+ EL0 = 0,
+ EL1 = 1,
+ EL2 = 2,
+ EL3 = 3
+ } ExceptionLevel;
+
+ typedef enum
+ {
+ ExtendType_SXTB,
+ ExtendType_SXTH,
+ ExtendType_SXTW,
+ ExtendType_SXTX,
+ ExtendType_UXTB,
+ ExtendType_UXTH,
+ ExtendType_UXTW,
+ ExtendType_UXTX
+ } ExtendType;
+
+ typedef enum
+ {
+ ExtractType_LEFT,
+ ExtractType_RIGHT
+ } ExtractType;
+
+ typedef enum
+ {
+ LogicalOp_AND,
+ LogicalOp_EOR,
+ LogicalOp_ORR
+ } LogicalOp;
+
+ typedef enum
+ {
+ MemOp_LOAD,
+ MemOp_STORE,
+ MemOp_PREFETCH,
+ MemOp_NOP
+ } MemOp;
+
+ typedef enum
+ {
+ MoveWideOp_N,
+ MoveWideOp_Z,
+ MoveWideOp_K
+ } MoveWideOp;
+
+ typedef enum {
+ ShiftType_LSL,
+ ShiftType_LSR,
+ ShiftType_ASR,
+ ShiftType_ROR
+ } ShiftType;
+
+ typedef enum
+ {
+ SP0 = 0,
+ SPx = 1
+ } StackPointerSelection;
+
+ typedef enum
+ {
+ Unpredictable_WBOVERLAP,
+ Unpredictable_LDPOVERLAP
+ } Unpredictable;
+
+ typedef enum
+ {
+ Constraint_NONE,
+ Constraint_UNKNOWN,
+ Constraint_SUPPRESSWB,
+ Constraint_NOP
+ } ConstraintType;
+
+ typedef enum
+ {
+ AccType_NORMAL,
+ AccType_UNPRIV,
+ AccType_STREAM,
+ AccType_ALIGNED,
+ AccType_ORDERED
+ } AccType;
+
+ typedef struct
+ {
+ uint32_t
+ N:1,
+ V:1,
+ C:1,
+ Z:1, // condition code flags – can also be accessed as PSTATE.[N,Z,C,V]
+ Q:1, // AArch32 only – CSPR.Q bit
+ IT:8, // AArch32 only – CPSR.IT bits
+ J:1, // AArch32 only – CSPR.J bit
+ T:1, // AArch32 only – CPSR.T bit
+ SS:1, // Single step process state bit
+ IL:1, // Illegal state bit
+ D:1,
+ A:1,
+ I:1,
+ F:1, // Interrupt masks – can also be accessed as PSTATE.[D,A,I,F]
+ E:1, // AArch32 only – CSPR.E bit
+ M:5, // AArch32 only – mode encodings
+ RW:1, // Current register width – 0 is AArch64, 1 is AArch32
+ EL:2, // Current exception level (see ExceptionLevel enum)
+ SP:1; // AArch64 only - Stack Pointer selection (see StackPointerSelection enum)
+ } ProcState;
+
+protected:
+
+ typedef struct
+ {
+ uint32_t mask;
+ uint32_t value;
+ uint32_t vfp_variants;
+ bool (EmulateInstructionARM64::*callback) (const uint32_t opcode);
+ const char *name;
+ } Opcode;
+
+ static Opcode*
+ GetOpcodeForInstruction (const uint32_t opcode);
+
+ bool
+ Emulate_addsub_imm (const uint32_t opcode);
+
+// bool
+// Emulate_STP_Q_ldstpair_off (const uint32_t opcode);
+//
+// bool
+// Emulate_STP_S_ldstpair_off (const uint32_t opcode);
+//
+// bool
+// Emulate_STP_32_ldstpair_off (const uint32_t opcode);
+//
+// bool
+// Emulate_STP_D_ldstpair_off (const uint32_t opcode);
+//
+ bool
+ Emulate_ldstpair_off (const uint32_t opcode);
+
+ bool
+ Emulate_ldstpair_pre (const uint32_t opcode);
+
+ bool
+ Emulate_ldstpair (const uint32_t opcode, AddrMode a_mode);
+
+ ProcState m_opcode_pstate;
+ ProcState m_emulated_pstate; // This can get updated by the opcode.
+ bool m_ignore_conditions;
+};
+
+#endif // EmulateInstructionARM64_h_
diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
new file mode 100644
index 000000000000..905984d33410
--- /dev/null
+++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
@@ -0,0 +1,430 @@
+//===-- JITLoaderGDB.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
+
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Symbol/SymbolVendor.h"
+
+#include "JITLoaderGDB.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+// Debug Interface Structures
+//------------------------------------------------------------------
+typedef enum
+{
+ JIT_NOACTION = 0,
+ JIT_REGISTER_FN,
+ JIT_UNREGISTER_FN
+} jit_actions_t;
+
+struct jit_code_entry
+{
+ struct jit_code_entry *next_entry;
+ struct jit_code_entry *prev_entry;
+ const char *symfile_addr;
+ uint64_t symfile_size;
+};
+
+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;
+};
+
+JITLoaderGDB::JITLoaderGDB (lldb_private::Process *process) :
+ JITLoader(process),
+ m_jit_objects(),
+ m_jit_break_id(LLDB_INVALID_BREAK_ID),
+ m_jit_descriptor_addr(LLDB_INVALID_ADDRESS)
+{
+}
+
+JITLoaderGDB::~JITLoaderGDB ()
+{
+ if (LLDB_BREAK_ID_IS_VALID(m_jit_break_id))
+ m_process->GetTarget().RemoveBreakpointByID (m_jit_break_id);
+}
+
+void JITLoaderGDB::DidAttach()
+{
+ Target &target = m_process->GetTarget();
+ ModuleList &module_list = target.GetImages();
+ SetJITBreakpoint(module_list);
+}
+
+void JITLoaderGDB::DidLaunch()
+{
+ Target &target = m_process->GetTarget();
+ ModuleList &module_list = target.GetImages();
+ SetJITBreakpoint(module_list);
+}
+
+void
+JITLoaderGDB::ModulesDidLoad(ModuleList &module_list)
+{
+ if (!DidSetJITBreakpoint() && m_process->IsAlive())
+ SetJITBreakpoint(module_list);
+}
+
+//------------------------------------------------------------------
+// Setup the JIT Breakpoint
+//------------------------------------------------------------------
+void
+JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list)
+{
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
+
+ if ( DidSetJITBreakpoint() )
+ return;
+
+ if (log)
+ log->Printf("JITLoaderGDB::%s looking for JIT register hook",
+ __FUNCTION__);
+
+ addr_t jit_addr = GetSymbolAddress(module_list,
+ ConstString("__jit_debug_register_code"),
+ eSymbolTypeAny);
+ if (jit_addr == LLDB_INVALID_ADDRESS)
+ return;
+
+ m_jit_descriptor_addr = GetSymbolAddress(module_list,
+ ConstString("__jit_debug_descriptor"),
+ eSymbolTypeData);
+ if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS)
+ {
+ if (log)
+ log->Printf(
+ "JITLoaderGDB::%s failed to find JIT descriptor address",
+ __FUNCTION__);
+ return;
+ }
+
+ if (log)
+ log->Printf("JITLoaderGDB::%s setting JIT breakpoint",
+ __FUNCTION__);
+
+ Breakpoint *bp =
+ m_process->GetTarget().CreateBreakpoint(jit_addr, true, false).get();
+ bp->SetCallback(JITDebugBreakpointHit, this, true);
+ bp->SetBreakpointKind("jit-debug-register");
+ m_jit_break_id = bp->GetID();
+
+ ReadJITDescriptor(true);
+}
+
+bool
+JITLoaderGDB::JITDebugBreakpointHit(void *baton,
+ StoppointCallbackContext *context,
+ user_id_t break_id, user_id_t break_loc_id)
+{
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
+ if (log)
+ log->Printf("JITLoaderGDB::%s hit JIT breakpoint",
+ __FUNCTION__);
+ JITLoaderGDB *instance = static_cast<JITLoaderGDB *>(baton);
+ return instance->ReadJITDescriptor(false);
+}
+
+static void updateSectionLoadAddress(const SectionList &section_list,
+ Target &target,
+ uint64_t symbolfile_addr,
+ uint64_t symbolfile_size,
+ uint64_t &vmaddrheuristic,
+ uint64_t &min_addr,
+ uint64_t &max_addr)
+{
+ const uint32_t num_sections = section_list.GetSize();
+ for (uint32_t i = 0; i<num_sections; ++i)
+ {
+ SectionSP section_sp(section_list.GetSectionAtIndex(i));
+ if (section_sp)
+ {
+ if(section_sp->IsFake()) {
+ uint64_t lower = (uint64_t)-1;
+ uint64_t upper = 0;
+ updateSectionLoadAddress(section_sp->GetChildren(), target, symbolfile_addr, symbolfile_size, vmaddrheuristic,
+ lower, upper);
+ if (lower < min_addr)
+ min_addr = lower;
+ if (upper > max_addr)
+ max_addr = upper;
+ const lldb::addr_t slide_amount = lower - section_sp->GetFileAddress();
+ section_sp->Slide(slide_amount, false);
+ section_sp->GetChildren().Slide(-slide_amount, false);
+ section_sp->SetByteSize (upper - lower);
+ } else {
+ vmaddrheuristic += 2<<section_sp->GetLog2Align();
+ uint64_t lower;
+ if (section_sp->GetFileAddress() > vmaddrheuristic)
+ lower = section_sp->GetFileAddress();
+ else {
+ lower = symbolfile_addr+section_sp->GetFileOffset();
+ section_sp->SetFileAddress(symbolfile_addr+section_sp->GetFileOffset());
+ }
+ target.SetSectionLoadAddress(section_sp, lower, true);
+ uint64_t upper = lower + section_sp->GetByteSize();
+ if (lower < min_addr)
+ min_addr = lower;
+ if (upper > max_addr)
+ max_addr = upper;
+ // This is an upper bound, but a good enough heuristic
+ vmaddrheuristic += section_sp->GetByteSize();
+ }
+ }
+ }
+}
+
+bool
+JITLoaderGDB::ReadJITDescriptor(bool all_entries)
+{
+ if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
+ Target &target = m_process->GetTarget();
+ ModuleList &module_list = target.GetImages();
+
+ jit_descriptor jit_desc;
+ const size_t jit_desc_size = sizeof(jit_desc);
+ Error error;
+ size_t bytes_read = m_process->DoReadMemory(
+ m_jit_descriptor_addr, &jit_desc, jit_desc_size, error);
+ if (bytes_read != jit_desc_size || !error.Success())
+ {
+ if (log)
+ log->Printf("JITLoaderGDB::%s failed to read JIT descriptor",
+ __FUNCTION__);
+ return false;
+ }
+
+ jit_actions_t jit_action = (jit_actions_t)jit_desc.action_flag;
+ addr_t jit_relevant_entry = (addr_t)jit_desc.relevant_entry;
+ if (all_entries)
+ {
+ jit_action = JIT_REGISTER_FN;
+ jit_relevant_entry = (addr_t)jit_desc.first_entry;
+ }
+
+ while (jit_relevant_entry != 0)
+ {
+ 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())
+ {
+ if (log)
+ log->Printf(
+ "JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64,
+ __FUNCTION__, jit_relevant_entry);
+ return false;
+ }
+
+ const addr_t &symbolfile_addr = (addr_t)jit_entry.symfile_addr;
+ const size_t &symbolfile_size = (size_t)jit_entry.symfile_size;
+ ModuleSP module_sp;
+
+ if (jit_action == JIT_REGISTER_FN)
+ {
+ if (log)
+ log->Printf(
+ "JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64
+ " (%" PRIu64 " bytes)",
+ __FUNCTION__, symbolfile_addr, (uint64_t) symbolfile_size);
+
+ char jit_name[64];
+ snprintf(jit_name, 64, "JIT(0x%" PRIx64 ")", symbolfile_addr);
+ module_sp = m_process->ReadModuleFromMemory(
+ FileSpec(jit_name, false), symbolfile_addr, symbolfile_size);
+
+ if (module_sp && module_sp->GetObjectFile())
+ {
+ bool changed;
+ m_jit_objects.insert(std::make_pair(symbolfile_addr, module_sp));
+ if (module_sp->GetObjectFile()->GetPluginName() == ConstString("mach-o"))
+ {
+ ObjectFile *image_object_file = module_sp->GetObjectFile();
+ if (image_object_file)
+ {
+ const SectionList *section_list = image_object_file->GetSectionList ();
+ if (section_list)
+ {
+ uint64_t vmaddrheuristic = 0;
+ uint64_t lower = (uint64_t)-1;
+ uint64_t upper = 0;
+ updateSectionLoadAddress(*section_list, target, symbolfile_addr, symbolfile_size,
+ vmaddrheuristic, lower, upper);
+ }
+ }
+ }
+ else
+ {
+ module_sp->SetLoadAddress(target, 0, true, changed);
+ }
+
+ // load the symbol table right away
+ module_sp->GetObjectFile()->GetSymtab();
+
+ module_list.AppendIfNeeded(module_sp);
+
+ ModuleList module_list;
+ module_list.Append(module_sp);
+ target.ModulesDidLoad(module_list);
+ }
+ else
+ {
+ if (log)
+ log->Printf("JITLoaderGDB::%s failed to load module for "
+ "JIT entry at 0x%" PRIx64,
+ __FUNCTION__, symbolfile_addr);
+ }
+ }
+ else if (jit_action == JIT_UNREGISTER_FN)
+ {
+ if (log)
+ log->Printf(
+ "JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64,
+ __FUNCTION__, symbolfile_addr);
+
+ JITObjectMap::iterator it = m_jit_objects.find(symbolfile_addr);
+ if (it != m_jit_objects.end())
+ {
+ module_sp = it->second;
+ ObjectFile *image_object_file = module_sp->GetObjectFile();
+ if (image_object_file)
+ {
+ const SectionList *section_list = image_object_file->GetSectionList ();
+ if (section_list)
+ {
+ const uint32_t num_sections = section_list->GetSize();
+ for (uint32_t i = 0; i<num_sections; ++i)
+ {
+ SectionSP section_sp(section_list->GetSectionAtIndex(i));
+ if (section_sp)
+ {
+ target.GetSectionLoadList().SetSectionUnloaded (section_sp);
+ }
+ }
+ }
+ }
+ module_list.Remove(module_sp);
+ m_jit_objects.erase(it);
+ }
+ }
+ else if (jit_action == JIT_NOACTION)
+ {
+ // Nothing to do
+ }
+ else
+ {
+ assert(false && "Unknown jit action");
+ }
+
+ if (all_entries)
+ jit_relevant_entry = (addr_t)jit_entry.next_entry;
+ else
+ jit_relevant_entry = 0;
+ }
+
+ return false; // Continue Running.
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+JITLoaderGDB::GetPluginNameStatic()
+{
+ static ConstString g_name("gdb");
+ return g_name;
+}
+
+JITLoaderSP
+JITLoaderGDB::CreateInstance(Process *process, bool force)
+{
+ JITLoaderSP jit_loader_sp;
+ ArchSpec arch (process->GetTarget().GetArchitecture());
+ if (arch.GetTriple().getVendor() != llvm::Triple::Apple)
+ jit_loader_sp.reset(new JITLoaderGDB(process));
+ return jit_loader_sp;
+}
+
+const char *
+JITLoaderGDB::GetPluginDescriptionStatic()
+{
+ return "JIT loader plug-in that watches for JIT events using the GDB interface.";
+}
+
+lldb_private::ConstString
+JITLoaderGDB::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+JITLoaderGDB::GetPluginVersion()
+{
+ return 1;
+}
+
+void
+JITLoaderGDB::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ CreateInstance);
+}
+
+void
+JITLoaderGDB::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+bool
+JITLoaderGDB::DidSetJITBreakpoint() const
+{
+ return LLDB_BREAK_ID_IS_VALID(m_jit_break_id);
+}
+
+addr_t
+JITLoaderGDB::GetSymbolAddress(ModuleList &module_list, const ConstString &name,
+ SymbolType symbol_type) const
+{
+ SymbolContextList target_symbols;
+ Target &target = m_process->GetTarget();
+
+ if (!module_list.FindSymbolsWithNameAndType(name, symbol_type,
+ target_symbols))
+ return LLDB_INVALID_ADDRESS;
+
+ SymbolContext sym_ctx;
+ target_symbols.GetContextAtIndex(0, sym_ctx);
+
+ const Address *jit_descriptor_addr = &sym_ctx.symbol->GetAddress();
+ if (!jit_descriptor_addr || !jit_descriptor_addr->IsValid())
+ return LLDB_INVALID_ADDRESS;
+
+ const addr_t jit_addr = jit_descriptor_addr->GetLoadAddress(&target);
+ return jit_addr;
+}
diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.h b/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
new file mode 100644
index 000000000000..5fa66b874972
--- /dev/null
+++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
@@ -0,0 +1,104 @@
+//===-- JITLoaderGDB.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_JITLoaderGDB_h_
+#define liblldb_JITLoaderGDB_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <vector>
+#include <string>
+
+#include "lldb/Target/JITLoader.h"
+#include "lldb/Target/Process.h"
+
+class JITLoaderGDB : public lldb_private::JITLoader
+{
+public:
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ static lldb::JITLoaderSP
+ CreateInstance (lldb_private::Process *process, bool force);
+
+ JITLoaderGDB (lldb_private::Process *process);
+
+ virtual
+ ~JITLoaderGDB ();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual lldb_private::ConstString
+ GetPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+ //------------------------------------------------------------------
+ // JITLoader interface
+ //------------------------------------------------------------------
+ virtual void
+ DidAttach ();
+
+ virtual void
+ DidLaunch ();
+
+ virtual void
+ ModulesDidLoad (lldb_private::ModuleList &module_list);
+
+private:
+ lldb::addr_t
+ GetSymbolAddress(lldb_private::ModuleList &module_list,
+ const lldb_private::ConstString &name,
+ lldb::SymbolType symbol_type) const;
+
+ void
+ SetJITBreakpoint(lldb_private::ModuleList &module_list);
+
+ bool
+ DidSetJITBreakpoint() const;
+
+ bool
+ ReadJITDescriptor(bool all_entries);
+
+ static bool
+ JITDebugBreakpointHit(void *baton,
+ lldb_private::StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ static void
+ ProcessStateChangedCallback(void *baton,
+ lldb_private::Process *process,
+ lldb::StateType state);
+
+ // A collection of in-memory jitted object addresses and their corresponding modules
+ typedef std::map<lldb::addr_t, const lldb::ModuleSP> JITObjectMap;
+ JITObjectMap m_jit_objects;
+
+ lldb::user_id_t m_jit_break_id;
+ lldb::addr_t m_jit_descriptor_addr;
+
+};
+
+#endif
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 9781dcb093ac..a6c74f3f1fc4 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -107,7 +107,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
if (symbol != NULL)
{
const char *name = symbol->GetMangled().GetDemangledName().AsCString();
- if (strstr(name, vtable_demangled_prefix) == name)
+ if (name && strstr(name, vtable_demangled_prefix) == name)
{
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
@@ -289,7 +289,9 @@ ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType
{
// FIXME: We have to check the process and make sure we actually know that this process supports
// the Itanium ABI.
- if (language == eLanguageTypeC_plus_plus)
+ if (language == eLanguageTypeC_plus_plus ||
+ language == eLanguageTypeC_plus_plus_03 ||
+ language == eLanguageTypeC_plus_plus_11)
return new ItaniumABILanguageRuntime (process);
else
return NULL;
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
index 32574e3ef2f0..0263c23ce307 100644
--- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -74,6 +74,25 @@ ObjectContainerBSDArchive::Object::Extract (const DataExtractor& data, lldb::off
size_t ar_name_len = 0;
std::string str;
char *err;
+
+
+ // File header
+ //
+ // The common format is as follows.
+ //
+ // Offset Length Name Format
+ // 0 16 File name ASCII right padded with spaces (no spaces allowed in file name)
+ // 16 12 File mod Decimal as cstring right padded with spaces
+ // 28 6 Owner ID Decimal as cstring right padded with spaces
+ // 34 6 Group ID Decimal as cstring right padded with spaces
+ // 40 8 File mode Octal as cstring right padded with spaces
+ // 48 10 File byte size Decimal as cstring right padded with spaces
+ // 58 2 File magic 0x60 0x0A
+
+ // Make sure there is enough data for the file header and bail if not
+ if (!data.ValidOffsetForDataOfSize(offset, 60))
+ return LLDB_INVALID_OFFSET;
+
str.assign ((const char *)data.GetData(&offset, 16), 16);
if (str.find("#1/") == 0)
{
@@ -110,7 +129,11 @@ ObjectContainerBSDArchive::Object::Extract (const DataExtractor& data, lldb::off
{
if (ar_name_len > 0)
{
- str.assign ((const char *)data.GetData(&offset, ar_name_len), ar_name_len);
+ const void *ar_name_ptr = data.GetData(&offset, ar_name_len);
+ // Make sure there was enough data for the string value and bail if not
+ if (ar_name_ptr == NULL)
+ return LLDB_INVALID_OFFSET;
+ str.assign ((const char *)ar_name_ptr, ar_name_len);
ar_name.SetCString (str.c_str());
}
ar_file_offset = offset;
@@ -224,7 +247,7 @@ ObjectContainerBSDArchive::Archive::FindCachedArchive (const FileSpec &file, con
// whose modification time doesn't match. It doesn't make sense
// for us to continue to use this BSD archive since we cache only
// the object info which consists of file time info and also the
- // file offset and file size of any contianed objects. Since
+ // file offset and file size of any contained objects. Since
// this information is now out of date, we won't get the correct
// information if we go and extract the file data, so we should
// remove the old and outdated entry.
@@ -335,7 +358,9 @@ ObjectContainerBSDArchive::CreateInstance
Timer scoped_timer (__PRETTY_FUNCTION__,
"ObjectContainerBSDArchive::CreateInstance (module = %s, file = %p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")",
module_sp->GetFileSpec().GetPath().c_str(),
- file, (uint64_t) file_offset, (uint64_t) length);
+ static_cast<const void*>(file),
+ static_cast<uint64_t>(file_offset),
+ static_cast<uint64_t>(length));
// Map the entire .a file to be sure that we don't lose any data if the file
// gets updated by a new build while this .a file is being used for debugging
@@ -457,11 +482,11 @@ ObjectContainerBSDArchive::ParseHeader ()
void
ObjectContainerBSDArchive::Dump (Stream *s) const
{
- s->Printf("%p: ", this);
+ s->Printf("%p: ", static_cast<const void*>(this));
s->Indent();
const size_t num_archs = GetNumArchitectures();
const size_t num_objects = GetNumObjects();
- s->Printf("ObjectContainerBSDArchive, num_archs = %zu, num_objects = %zu", num_archs, num_objects);
+ s->Printf("ObjectContainerBSDArchive, num_archs = %" PRIu64 ", num_objects = %" PRIu64 "", (uint64_t)num_archs, (uint64_t)num_objects);
uint32_t i;
ArchSpec arch;
s->IndentMore();
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
index a63a01d7ed7a..f027294b7c57 100644
--- a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
+++ b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
@@ -183,6 +183,12 @@ ELFHeader::GetRelocationJumpSlotType() const
case EM_ARM:
slot = R_ARM_JUMP_SLOT;
break;
+ case EM_HEXAGON:
+ slot = R_HEX_JMP_SLOT;
+ break;
+ case EM_AARCH64:
+ slot = R_AARCH64_JUMP_SLOT;
+ break;
}
return slot;
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.h b/source/Plugins/ObjectFile/ELF/ELFHeader.h
index aa2c16b6168c..4ea22b51baf7 100644
--- a/source/Plugins/ObjectFile/ELF/ELFHeader.h
+++ b/source/Plugins/ObjectFile/ELF/ELFHeader.h
@@ -353,7 +353,7 @@ struct ELFRel
}
/// Returns the symbol index when the given entry represents a 32-bit
- /// reloction.
+ /// relocation.
static unsigned
RelocSymbol32(const ELFRel &rel)
{
@@ -361,7 +361,7 @@ struct ELFRel
}
/// Returns the symbol index when the given entry represents a 64-bit
- /// reloction.
+ /// relocation.
static unsigned
RelocSymbol64(const ELFRel &rel)
{
@@ -412,7 +412,7 @@ struct ELFRela
}
/// Returns the symbol index when the given entry represents a 32-bit
- /// reloction.
+ /// relocation.
static unsigned
RelocSymbol32(const ELFRela &rela)
{
@@ -420,7 +420,7 @@ struct ELFRela
}
/// Returns the symbol index when the given entry represents a 64-bit
- /// reloction.
+ /// relocation.
static unsigned
RelocSymbol64(const ELFRela &rela)
{
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 335090cc0c36..d86aee78947f 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -22,13 +22,16 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
-#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MathExtras.h"
#define CASE_AND_STREAM(s, def, width) \
case def: s->Printf("%-*s", width, #def); break;
@@ -39,6 +42,30 @@ using namespace elf;
using namespace llvm::ELF;
namespace {
+
+// ELF note owner definitions
+const char *const LLDB_NT_OWNER_FREEBSD = "FreeBSD";
+const char *const LLDB_NT_OWNER_GNU = "GNU";
+const char *const LLDB_NT_OWNER_NETBSD = "NetBSD";
+const char *const LLDB_NT_OWNER_CSR = "csr";
+
+// ELF note type definitions
+const elf_word LLDB_NT_FREEBSD_ABI_TAG = 0x01;
+const elf_word LLDB_NT_FREEBSD_ABI_SIZE = 4;
+
+const elf_word LLDB_NT_GNU_ABI_TAG = 0x01;
+const elf_word LLDB_NT_GNU_ABI_SIZE = 16;
+
+const elf_word LLDB_NT_GNU_BUILD_ID_TAG = 0x03;
+
+const elf_word LLDB_NT_NETBSD_ABI_TAG = 0x01;
+const elf_word LLDB_NT_NETBSD_ABI_SIZE = 4;
+
+// GNU ABI note OS constants
+const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00;
+const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01;
+const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;
+
//===----------------------------------------------------------------------===//
/// @class ELFRelocation
/// @brief Generic wrapper for ELFRel and ELFRela.
@@ -72,6 +99,18 @@ public:
static unsigned
RelocSymbol64(const ELFRelocation &rel);
+ static unsigned
+ RelocOffset32(const ELFRelocation &rel);
+
+ static unsigned
+ RelocOffset64(const ELFRelocation &rel);
+
+ static unsigned
+ RelocAddend32(const ELFRelocation &rel);
+
+ static unsigned
+ RelocAddend64(const ELFRelocation &rel);
+
private:
typedef llvm::PointerUnion<ELFRel*, ELFRela*> RelocUnion;
@@ -80,9 +119,9 @@ private:
ELFRelocation::ELFRelocation(unsigned type)
{
- if (type == DT_REL)
+ if (type == DT_REL || type == SHT_REL)
reloc = new ELFRel();
- else if (type == DT_RELA)
+ else if (type == DT_RELA || type == SHT_RELA)
reloc = new ELFRela();
else {
assert(false && "unexpected relocation type");
@@ -143,6 +182,42 @@ ELFRelocation::RelocSymbol64(const ELFRelocation &rel)
return ELFRela::RelocSymbol64(*rel.reloc.get<ELFRela*>());
}
+unsigned
+ELFRelocation::RelocOffset32(const ELFRelocation &rel)
+{
+ if (rel.reloc.is<ELFRel*>())
+ return rel.reloc.get<ELFRel*>()->r_offset;
+ else
+ return rel.reloc.get<ELFRela*>()->r_offset;
+}
+
+unsigned
+ELFRelocation::RelocOffset64(const ELFRelocation &rel)
+{
+ if (rel.reloc.is<ELFRel*>())
+ return rel.reloc.get<ELFRel*>()->r_offset;
+ else
+ return rel.reloc.get<ELFRela*>()->r_offset;
+}
+
+unsigned
+ELFRelocation::RelocAddend32(const ELFRelocation &rel)
+{
+ if (rel.reloc.is<ELFRel*>())
+ return 0;
+ else
+ return rel.reloc.get<ELFRela*>()->r_addend;
+}
+
+unsigned
+ELFRelocation::RelocAddend64(const ELFRelocation &rel)
+{
+ if (rel.reloc.is<ELFRel*>())
+ return 0;
+ else
+ return rel.reloc.get<ELFRela*>()->r_addend;
+}
+
} // end anonymous namespace
bool
@@ -183,6 +258,39 @@ ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset)
return true;
}
+static uint32_t
+kalimbaVariantFromElfFlags(const elf::elf_word e_flags)
+{
+ const uint32_t dsp_rev = e_flags & 0xFF;
+ uint32_t kal_arch_variant = LLDB_INVALID_CPUTYPE;
+ switch(dsp_rev)
+ {
+ // TODO(mg11) Support more variants
+ case 10:
+ kal_arch_variant = 3;
+ break;
+ case 14:
+ kal_arch_variant = 4;
+ break;
+ default:
+ break;
+ }
+ return kal_arch_variant;
+}
+
+static uint32_t
+subTypeFromElfHeader(const elf::ELFHeader& header)
+{
+ return
+ llvm::ELF::EM_CSR_KALIMBA == header.e_machine ?
+ kalimbaVariantFromElfFlags(header.e_flags) :
+ LLDB_INVALID_CPUTYPE;
+}
+
+// Arbitrary constant used as UUID prefix for core files.
+const uint32_t
+ObjectFileELF::g_core_uuid_magic(0xE210C);
+
//------------------------------------------------------------------
// Static methods.
//------------------------------------------------------------------
@@ -261,6 +369,22 @@ ObjectFileELF::CreateMemoryInstance (const lldb::ModuleSP &module_sp,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr)
{
+ if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT))
+ {
+ const uint8_t *magic = data_sp->GetBytes();
+ if (ELFHeader::MagicBytesMatch(magic))
+ {
+ unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
+ if (address_size == 4 || address_size == 8)
+ {
+ std::auto_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(module_sp, data_sp, process_sp, header_addr));
+ ArchSpec spec;
+ if (objfile_ap->GetArchitecture(spec) &&
+ objfile_ap->SetModulesArchitecture(spec))
+ return objfile_ap.release();
+ }
+ }
+ }
return NULL;
}
@@ -284,7 +408,7 @@ ObjectFileELF::MagicBytesMatch (DataBufferSP& data_sp,
* code or tables extracted from it, as desired without restriction.
*/
static uint32_t
-calc_gnu_debuglink_crc32(const void *buf, size_t size)
+calc_crc32(uint32_t crc, const void *buf, size_t size)
{
static const uint32_t g_crc32_tab[] =
{
@@ -333,14 +457,100 @@ calc_gnu_debuglink_crc32(const void *buf, size_t size)
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
const uint8_t *p = (const uint8_t *)buf;
- uint32_t crc;
- crc = ~0U;
+ crc = crc ^ ~0U;
while (size--)
crc = g_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
return crc ^ ~0U;
}
+static uint32_t
+calc_gnu_debuglink_crc32(const void *buf, size_t size)
+{
+ return calc_crc32(0U, buf, size);
+}
+
+uint32_t
+ObjectFileELF::CalculateELFNotesSegmentsCRC32 (const ProgramHeaderColl& program_headers,
+ DataExtractor& object_data)
+{
+ typedef ProgramHeaderCollConstIter Iter;
+
+ uint32_t core_notes_crc = 0;
+
+ for (Iter I = program_headers.begin(); I != program_headers.end(); ++I)
+ {
+ if (I->p_type == llvm::ELF::PT_NOTE)
+ {
+ const elf_off ph_offset = I->p_offset;
+ const size_t ph_size = I->p_filesz;
+
+ DataExtractor segment_data;
+ if (segment_data.SetData(object_data, ph_offset, ph_size) != ph_size)
+ {
+ // The ELF program header contained incorrect data,
+ // probably corefile is incomplete or corrupted.
+ break;
+ }
+
+ core_notes_crc = calc_crc32(core_notes_crc,
+ segment_data.GetDataStart(),
+ segment_data.GetByteSize());
+ }
+ }
+
+ return core_notes_crc;
+}
+
+static const char*
+OSABIAsCString (unsigned char osabi_byte)
+{
+#define _MAKE_OSABI_CASE(x) case x: return #x
+ switch (osabi_byte)
+ {
+ _MAKE_OSABI_CASE(ELFOSABI_NONE);
+ _MAKE_OSABI_CASE(ELFOSABI_HPUX);
+ _MAKE_OSABI_CASE(ELFOSABI_NETBSD);
+ _MAKE_OSABI_CASE(ELFOSABI_GNU);
+ _MAKE_OSABI_CASE(ELFOSABI_HURD);
+ _MAKE_OSABI_CASE(ELFOSABI_SOLARIS);
+ _MAKE_OSABI_CASE(ELFOSABI_AIX);
+ _MAKE_OSABI_CASE(ELFOSABI_IRIX);
+ _MAKE_OSABI_CASE(ELFOSABI_FREEBSD);
+ _MAKE_OSABI_CASE(ELFOSABI_TRU64);
+ _MAKE_OSABI_CASE(ELFOSABI_MODESTO);
+ _MAKE_OSABI_CASE(ELFOSABI_OPENBSD);
+ _MAKE_OSABI_CASE(ELFOSABI_OPENVMS);
+ _MAKE_OSABI_CASE(ELFOSABI_NSK);
+ _MAKE_OSABI_CASE(ELFOSABI_AROS);
+ _MAKE_OSABI_CASE(ELFOSABI_FENIXOS);
+ _MAKE_OSABI_CASE(ELFOSABI_C6000_ELFABI);
+ _MAKE_OSABI_CASE(ELFOSABI_C6000_LINUX);
+ _MAKE_OSABI_CASE(ELFOSABI_ARM);
+ _MAKE_OSABI_CASE(ELFOSABI_STANDALONE);
+ default:
+ return "<unknown-osabi>";
+ }
+#undef _MAKE_OSABI_CASE
+}
+
+static bool
+GetOsFromOSABI (unsigned char osabi_byte, llvm::Triple::OSType &ostype)
+{
+ switch (osabi_byte)
+ {
+ case ELFOSABI_AIX: ostype = llvm::Triple::OSType::AIX; break;
+ case ELFOSABI_FREEBSD: ostype = llvm::Triple::OSType::FreeBSD; break;
+ case ELFOSABI_GNU: ostype = llvm::Triple::OSType::Linux; break;
+ case ELFOSABI_NETBSD: ostype = llvm::Triple::OSType::NetBSD; break;
+ case ELFOSABI_OPENBSD: ostype = llvm::Triple::OSType::OpenBSD; break;
+ case ELFOSABI_SOLARIS: ostype = llvm::Triple::OSType::Solaris; break;
+ default:
+ ostype = llvm::Triple::OSType::UnknownOS;
+ }
+ return ostype != llvm::Triple::OSType::UnknownOS;
+}
+
size_t
ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
lldb::DataBufferSP& data_sp,
@@ -349,6 +559,8 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
lldb::offset_t length,
lldb_private::ModuleSpecList &specs)
{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES));
+
const size_t initial_count = specs.GetSize();
if (ObjectFileELF::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
@@ -362,18 +574,30 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
{
ModuleSpec spec;
spec.GetFileSpec() = file;
+
+ const uint32_t sub_type = subTypeFromElfHeader(header);
spec.GetArchitecture().SetArchitecture(eArchTypeELF,
header.e_machine,
- LLDB_INVALID_CPUTYPE);
+ sub_type);
+
if (spec.GetArchitecture().IsValid())
{
- // We could parse the ABI tag information (in .note, .notes, or .note.ABI-tag) to get the
- // machine information. However, this info isn't guaranteed to exist or be correct. Details:
- // http://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/noteabitag.html
- // Instead of passing potentially incorrect information down the pipeline, grab
- // the host information and use it.
- spec.GetArchitecture().GetTriple().setOSName (Host::GetOSString().GetCString());
- spec.GetArchitecture().GetTriple().setVendorName(Host::GetVendorString().GetCString());
+ llvm::Triple::OSType ostype;
+ // First try to determine the OS type from the OSABI field in the elf header.
+
+ if (log)
+ log->Printf ("ObjectFileELF::%s file '%s' module OSABI: %s", __FUNCTION__, file.GetPath ().c_str (), OSABIAsCString (header.e_ident[EI_OSABI]));
+ if (GetOsFromOSABI (header.e_ident[EI_OSABI], ostype) && ostype != llvm::Triple::OSType::UnknownOS)
+ {
+ spec.GetArchitecture ().GetTriple ().setOS (ostype);
+
+ // Also clear the vendor so we don't end up with situations like
+ // x86_64-apple-FreeBSD.
+ spec.GetArchitecture ().GetTriple ().setVendor (llvm::Triple::VendorType::UnknownVendor);
+
+ if (log)
+ log->Printf ("ObjectFileELF::%s file '%s' set ELF module OS type from ELF header OSABI.", __FUNCTION__, file.GetPath ().c_str ());
+ }
// Try to get the UUID from the section list. Usually that's at the end, so
// map the file in if we don't have it already.
@@ -388,16 +612,68 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
std::string gnu_debuglink_file;
SectionHeaderColl section_headers;
lldb_private::UUID &uuid = spec.GetUUID();
- GetSectionHeaderInfo(section_headers, data, header, uuid, gnu_debuglink_file, gnu_debuglink_crc);
+
+ GetSectionHeaderInfo(section_headers, data, header, uuid, gnu_debuglink_file, gnu_debuglink_crc, spec.GetArchitecture ());
+
+ // If the module vendor is not set and the module OS matches this host OS, set the module vendor to the host vendor.
+ llvm::Triple &spec_triple = spec.GetArchitecture ().GetTriple ();
+ if (spec_triple.getVendor () == llvm::Triple::VendorType::UnknownVendor)
+ {
+ const llvm::Triple &host_triple = HostInfo::GetArchitecture().GetTriple();
+ if (spec_triple.getOS () == host_triple.getOS ())
+ spec_triple.setVendor (host_triple.getVendor ());
+ }
+
+ if (log)
+ log->Printf ("ObjectFileELF::%s file '%s' module set to triple: %s (architecture %s)", __FUNCTION__, file.GetPath ().c_str (), spec_triple.getTriple ().c_str (), spec.GetArchitecture ().GetArchitectureName ());
if (!uuid.IsValid())
{
+ uint32_t core_notes_crc = 0;
+
if (!gnu_debuglink_crc)
{
- // Need to map entire file into memory to calculate the crc.
- data_sp = file.MemoryMapFileContents (file_offset, SIZE_MAX);
- data.SetData(data_sp);
- gnu_debuglink_crc = calc_gnu_debuglink_crc32 (data.GetDataStart(), data.GetByteSize());
+ lldb_private::Timer scoped_timer (__PRETTY_FUNCTION__,
+ "Calculating module crc32 %s with size %" PRIu64 " KiB",
+ file.GetLastPathComponent().AsCString(),
+ (file.GetByteSize()-file_offset)/1024);
+
+ // For core files - which usually don't happen to have a gnu_debuglink,
+ // and are pretty bulky - calculating whole contents crc32 would be too much of luxury.
+ // Thus we will need to fallback to something simpler.
+ if (header.e_type == llvm::ELF::ET_CORE)
+ {
+ size_t program_headers_end = header.e_phoff + header.e_phnum * header.e_phentsize;
+ if (program_headers_end > data_sp->GetByteSize())
+ {
+ data_sp = file.MemoryMapFileContents(file_offset, program_headers_end);
+ data.SetData(data_sp);
+ }
+ ProgramHeaderColl program_headers;
+ GetProgramHeaderInfo(program_headers, data, header);
+
+ size_t segment_data_end = 0;
+ for (ProgramHeaderCollConstIter I = program_headers.begin();
+ I != program_headers.end(); ++I)
+ {
+ segment_data_end = std::max<unsigned long long> (I->p_offset + I->p_filesz, segment_data_end);
+ }
+
+ if (segment_data_end > data_sp->GetByteSize())
+ {
+ data_sp = file.MemoryMapFileContents(file_offset, segment_data_end);
+ data.SetData(data_sp);
+ }
+
+ core_notes_crc = CalculateELFNotesSegmentsCRC32 (program_headers, data);
+ }
+ else
+ {
+ // Need to map entire file into memory to calculate the crc.
+ data_sp = file.MemoryMapFileContents (file_offset, SIZE_MAX);
+ data.SetData(data_sp);
+ gnu_debuglink_crc = calc_gnu_debuglink_crc32 (data.GetDataStart(), data.GetByteSize());
+ }
}
if (gnu_debuglink_crc)
{
@@ -405,6 +681,13 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
uint32_t uuidt[4] = { gnu_debuglink_crc, 0, 0, 0 };
uuid.SetBytes (uuidt, sizeof(uuidt));
}
+ else if (core_notes_crc)
+ {
+ // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it look different form
+ // .gnu_debuglink crc followed by 4 bytes of note segments crc.
+ uint32_t uuidt[4] = { g_core_uuid_magic, core_notes_crc, 0, 0 };
+ uuid.SetBytes (uuidt, sizeof(uuidt));
+ }
}
specs.Append(spec);
@@ -442,15 +725,38 @@ ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,
lldb::offset_t length) :
ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
m_header(),
+ m_uuid(),
+ m_gnu_debuglink_file(),
+ m_gnu_debuglink_crc(0),
m_program_headers(),
m_section_headers(),
- m_filespec_ap()
+ m_dynamic_symbols(),
+ m_filespec_ap(),
+ m_entry_point_address(),
+ m_arch_spec()
{
if (file)
m_file = *file;
::memset(&m_header, 0, sizeof(m_header));
- m_gnu_debuglink_crc = 0;
- m_gnu_debuglink_file.clear();
+}
+
+ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,
+ DataBufferSP& data_sp,
+ const lldb::ProcessSP &process_sp,
+ addr_t header_addr) :
+ ObjectFile(module_sp, process_sp, LLDB_INVALID_ADDRESS, data_sp),
+ m_header(),
+ m_uuid(),
+ m_gnu_debuglink_file(),
+ m_gnu_debuglink_crc(0),
+ m_program_headers(),
+ m_section_headers(),
+ m_dynamic_symbols(),
+ m_filespec_ap(),
+ m_entry_point_address(),
+ m_arch_spec()
+{
+ ::memset(&m_header, 0, sizeof(m_header));
}
ObjectFileELF::~ObjectFileELF()
@@ -460,7 +766,7 @@ ObjectFileELF::~ObjectFileELF()
bool
ObjectFileELF::IsExecutable() const
{
- return m_header.e_entry != 0;
+ return ((m_header.e_type & ET_EXEC) != 0) || (m_header.e_entry != 0);
}
bool
@@ -543,7 +849,7 @@ bool
ObjectFileELF::GetUUID(lldb_private::UUID* uuid)
{
// Need to parse the section list to get the UUIDs, so make sure that's been done.
- if (!ParseSectionHeaders())
+ if (!ParseSectionHeaders() && GetType() != ObjectFile::eTypeCoreFile)
return false;
if (m_uuid.IsValid())
@@ -552,7 +858,25 @@ ObjectFileELF::GetUUID(lldb_private::UUID* uuid)
*uuid = m_uuid;
return true;
}
- else
+ else if (GetType() == ObjectFile::eTypeCoreFile)
+ {
+ uint32_t core_notes_crc = 0;
+
+ if (!ParseProgramHeaders())
+ return false;
+
+ core_notes_crc = CalculateELFNotesSegmentsCRC32(m_program_headers, m_data);
+
+ if (core_notes_crc)
+ {
+ // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it
+ // look different form .gnu_debuglink crc - followed by 4 bytes of note
+ // segments crc.
+ uint32_t uuidt[4] = { g_core_uuid_magic, core_notes_crc, 0, 0 };
+ m_uuid.SetBytes (uuidt, sizeof(uuidt));
+ }
+ }
+ else
{
if (!m_gnu_debuglink_crc)
m_gnu_debuglink_crc = calc_gnu_debuglink_crc32 (m_data.GetDataStart(), m_data.GetByteSize());
@@ -560,11 +884,16 @@ ObjectFileELF::GetUUID(lldb_private::UUID* uuid)
{
// Use 4 bytes of crc from the .gnu_debuglink section.
uint32_t uuidt[4] = { m_gnu_debuglink_crc, 0, 0, 0 };
- uuid->SetBytes (uuidt, sizeof(uuidt));
- return true;
+ m_uuid.SetBytes (uuidt, sizeof(uuidt));
}
}
+ if (m_uuid.IsValid())
+ {
+ *uuid = m_uuid;
+ return true;
+ }
+
return false;
}
@@ -724,72 +1053,235 @@ ObjectFileELF::ParseDependentModules()
}
//----------------------------------------------------------------------
-// ParseProgramHeaders
+// GetProgramHeaderInfo
//----------------------------------------------------------------------
size_t
-ObjectFileELF::ParseProgramHeaders()
+ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
+ DataExtractor &object_data,
+ const ELFHeader &header)
{
// We have already parsed the program headers
- if (!m_program_headers.empty())
- return m_program_headers.size();
+ if (!program_headers.empty())
+ return program_headers.size();
// If there are no program headers to read we are done.
- if (m_header.e_phnum == 0)
+ if (header.e_phnum == 0)
return 0;
- m_program_headers.resize(m_header.e_phnum);
- if (m_program_headers.size() != m_header.e_phnum)
+ program_headers.resize(header.e_phnum);
+ if (program_headers.size() != header.e_phnum)
return 0;
- const size_t ph_size = m_header.e_phnum * m_header.e_phentsize;
- const elf_off ph_offset = m_header.e_phoff;
+ const size_t ph_size = header.e_phnum * header.e_phentsize;
+ const elf_off ph_offset = header.e_phoff;
DataExtractor data;
- if (GetData (ph_offset, ph_size, data) != ph_size)
+ if (data.SetData(object_data, ph_offset, ph_size) != ph_size)
return 0;
uint32_t idx;
lldb::offset_t offset;
- for (idx = 0, offset = 0; idx < m_header.e_phnum; ++idx)
+ for (idx = 0, offset = 0; idx < header.e_phnum; ++idx)
{
- if (m_program_headers[idx].Parse(data, &offset) == false)
+ if (program_headers[idx].Parse(data, &offset) == false)
break;
}
- if (idx < m_program_headers.size())
- m_program_headers.resize(idx);
+ if (idx < program_headers.size())
+ program_headers.resize(idx);
+
+ return program_headers.size();
- return m_program_headers.size();
}
-static bool
-ParseNoteGNUBuildID(DataExtractor &data, lldb_private::UUID &uuid)
+//----------------------------------------------------------------------
+// ParseProgramHeaders
+//----------------------------------------------------------------------
+size_t
+ObjectFileELF::ParseProgramHeaders()
+{
+ return GetProgramHeaderInfo(m_program_headers, m_data, m_header);
+}
+
+lldb_private::Error
+ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch_spec, lldb_private::UUID &uuid)
{
- // Try to parse the note section (ie .note.gnu.build-id|.notes|.note|...) and get the build id.
- // BuildID documentation: https://fedoraproject.org/wiki/Releases/FeatureBuildId
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES));
+ Error error;
+
lldb::offset_t offset = 0;
- static const uint32_t g_gnu_build_id = 3; // NT_GNU_BUILD_ID from elf.h
while (true)
{
+ // Parse the note header. If this fails, bail out.
ELFNote note = ELFNote();
if (!note.Parse(data, &offset))
- return false;
+ {
+ // We're done.
+ return error;
+ }
+
+ // If a tag processor handles the tag, it should set processed to true, and
+ // the loop will assume the tag processing has moved entirely past the note's payload.
+ // Otherwise, leave it false and the end of the loop will handle the offset properly.
+ bool processed = false;
- // 16 bytes is UUID|MD5, 20 bytes is SHA1
- if (note.n_name == "GNU" && (note.n_type == g_gnu_build_id) &&
- (note.n_descsz == 16 || note.n_descsz == 20))
+ if (log)
+ log->Printf ("ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, __FUNCTION__, note.n_name.c_str (), note.n_type);
+
+ // Process FreeBSD ELF notes.
+ if ((note.n_name == LLDB_NT_OWNER_FREEBSD) &&
+ (note.n_type == LLDB_NT_FREEBSD_ABI_TAG) &&
+ (note.n_descsz == LLDB_NT_FREEBSD_ABI_SIZE))
{
- uint8_t uuidbuf[20];
- if (data.GetU8 (&offset, &uuidbuf, note.n_descsz) == NULL)
- return false;
- uuid.SetBytes (uuidbuf, note.n_descsz);
- return true;
+ // We'll consume the payload below.
+ processed = true;
+
+ // Pull out the min version info.
+ uint32_t version_info;
+ if (data.GetU32 (&offset, &version_info, 1) == nullptr)
+ {
+ error.SetErrorString ("failed to read FreeBSD ABI note payload");
+ return error;
+ }
+
+ // Convert the version info into a major/minor number.
+ const uint32_t version_major = version_info / 100000;
+ const uint32_t version_minor = (version_info / 1000) % 100;
+
+ char os_name[32];
+ snprintf (os_name, sizeof (os_name), "freebsd%" PRIu32 ".%" PRIu32, version_major, version_minor);
+
+ // Set the elf OS version to FreeBSD. Also clear the vendor.
+ arch_spec.GetTriple ().setOSName (os_name);
+ arch_spec.GetTriple ().setVendor (llvm::Triple::VendorType::UnknownVendor);
+
+ if (log)
+ log->Printf ("ObjectFileELF::%s detected FreeBSD %" PRIu32 ".%" PRIu32 ".%" PRIu32, __FUNCTION__, version_major, version_minor, static_cast<uint32_t> (version_info % 1000));
+ }
+ // Process GNU ELF notes.
+ else if (note.n_name == LLDB_NT_OWNER_GNU)
+ {
+ switch (note.n_type)
+ {
+ case LLDB_NT_GNU_ABI_TAG:
+ if (note.n_descsz == LLDB_NT_GNU_ABI_SIZE)
+ {
+ // We'll consume the payload below.
+ processed = true;
+
+ // Pull out the min OS version supporting the ABI.
+ uint32_t version_info[4];
+ if (data.GetU32 (&offset, &version_info[0], note.n_descsz / 4) == nullptr)
+ {
+ error.SetErrorString ("failed to read GNU ABI note payload");
+ return error;
+ }
+
+ // Set the OS per the OS field.
+ switch (version_info[0])
+ {
+ case LLDB_NT_GNU_ABI_OS_LINUX:
+ arch_spec.GetTriple ().setOS (llvm::Triple::OSType::Linux);
+ arch_spec.GetTriple ().setVendor (llvm::Triple::VendorType::UnknownVendor);
+ if (log)
+ log->Printf ("ObjectFileELF::%s detected Linux, min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, __FUNCTION__, version_info[1], version_info[2], version_info[3]);
+ // FIXME we have the minimal version number, we could be propagating that. version_info[1] = OS Major, version_info[2] = OS Minor, version_info[3] = Revision.
+ break;
+ case LLDB_NT_GNU_ABI_OS_HURD:
+ arch_spec.GetTriple ().setOS (llvm::Triple::OSType::UnknownOS);
+ arch_spec.GetTriple ().setVendor (llvm::Triple::VendorType::UnknownVendor);
+ if (log)
+ log->Printf ("ObjectFileELF::%s detected Hurd (unsupported), min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, __FUNCTION__, version_info[1], version_info[2], version_info[3]);
+ break;
+ case LLDB_NT_GNU_ABI_OS_SOLARIS:
+ arch_spec.GetTriple ().setOS (llvm::Triple::OSType::Solaris);
+ arch_spec.GetTriple ().setVendor (llvm::Triple::VendorType::UnknownVendor);
+ if (log)
+ log->Printf ("ObjectFileELF::%s detected Solaris, min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, __FUNCTION__, version_info[1], version_info[2], version_info[3]);
+ break;
+ default:
+ if (log)
+ log->Printf ("ObjectFileELF::%s unrecognized OS in note, id %" PRIu32 ", min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, __FUNCTION__, version_info[0], version_info[1], version_info[2], version_info[3]);
+ break;
+ }
+ }
+ break;
+
+ case LLDB_NT_GNU_BUILD_ID_TAG:
+ // Only bother processing this if we don't already have the uuid set.
+ if (!uuid.IsValid())
+ {
+ // We'll consume the payload below.
+ processed = true;
+
+ // 16 bytes is UUID|MD5, 20 bytes is SHA1
+ if ((note.n_descsz == 16 || note.n_descsz == 20))
+ {
+ uint8_t uuidbuf[20];
+ if (data.GetU8 (&offset, &uuidbuf, note.n_descsz) == nullptr)
+ {
+ error.SetErrorString ("failed to read GNU_BUILD_ID note payload");
+ return error;
+ }
+
+ // Save the build id as the UUID for the module.
+ uuid.SetBytes (uuidbuf, note.n_descsz);
+ }
+ }
+ break;
+ }
}
- offset += llvm::RoundUpToAlignment(note.n_descsz, 4);
+ // Process NetBSD ELF notes.
+ else if ((note.n_name == LLDB_NT_OWNER_NETBSD) &&
+ (note.n_type == LLDB_NT_NETBSD_ABI_TAG) &&
+ (note.n_descsz == LLDB_NT_NETBSD_ABI_SIZE))
+ {
+
+ // We'll consume the payload below.
+ processed = true;
+
+ // Pull out the min version info.
+ uint32_t version_info;
+ if (data.GetU32 (&offset, &version_info, 1) == nullptr)
+ {
+ error.SetErrorString ("failed to read NetBSD ABI note payload");
+ return error;
+ }
+
+ // Set the elf OS version to NetBSD. Also clear the vendor.
+ arch_spec.GetTriple ().setOS (llvm::Triple::OSType::NetBSD);
+ arch_spec.GetTriple ().setVendor (llvm::Triple::VendorType::UnknownVendor);
+
+ if (log)
+ log->Printf ("ObjectFileELF::%s detected NetBSD, min version constant %" PRIu32, __FUNCTION__, version_info);
+ }
+ // Process CSR kalimba notes
+ else if ((note.n_type == LLDB_NT_GNU_ABI_TAG) &&
+ (note.n_name == LLDB_NT_OWNER_CSR))
+ {
+ // We'll consume the payload below.
+ processed = true;
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);
+ arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::CSR);
+
+ // TODO At some point the description string could be processed.
+ // It could provide a steer towards the kalimba variant which
+ // this ELF targets.
+ if(note.n_descsz)
+ {
+ const char *cstr = data.GetCStr(&offset, llvm::RoundUpToAlignment (note.n_descsz, 4));
+ (void)cstr;
+ }
+ }
+
+ if (!processed)
+ offset += llvm::RoundUpToAlignment(note.n_descsz, 4);
}
- return false;
+
+ return error;
}
+
//----------------------------------------------------------------------
// GetSectionHeaderInfo
//----------------------------------------------------------------------
@@ -799,16 +1291,51 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
const elf::ELFHeader &header,
lldb_private::UUID &uuid,
std::string &gnu_debuglink_file,
- uint32_t &gnu_debuglink_crc)
+ uint32_t &gnu_debuglink_crc,
+ ArchSpec &arch_spec)
{
- // We have already parsed the section headers
+ // Don't reparse the section headers if we already did that.
if (!section_headers.empty())
return section_headers.size();
+ // Only initialize the arch_spec to okay defaults if they're not already set.
+ // We'll refine this with note data as we parse the notes.
+ if (arch_spec.GetTriple ().getOS () == llvm::Triple::OSType::UnknownOS)
+ {
+ const uint32_t sub_type = subTypeFromElfHeader(header);
+ arch_spec.SetArchitecture (eArchTypeELF, header.e_machine, sub_type);
+
+ switch (arch_spec.GetAddressByteSize())
+ {
+ case 4:
+ {
+ const ArchSpec host_arch32 = HostInfo::GetArchitecture(HostInfo::eArchKind32);
+ if (host_arch32.GetCore() == arch_spec.GetCore())
+ {
+ arch_spec.GetTriple().setOSName(HostInfo::GetOSString().data());
+ arch_spec.GetTriple().setVendorName(HostInfo::GetVendorString().data());
+ }
+ }
+ break;
+ case 8:
+ {
+ const ArchSpec host_arch64 = HostInfo::GetArchitecture(HostInfo::eArchKind64);
+ if (host_arch64.GetCore() == arch_spec.GetCore())
+ {
+ arch_spec.GetTriple().setOSName(HostInfo::GetOSString().data());
+ arch_spec.GetTriple().setVendorName(HostInfo::GetVendorString().data());
+ }
+ }
+ break;
+ }
+ }
+
// If there are no section headers we are done.
if (header.e_shnum == 0)
return 0;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES));
+
section_headers.resize(header.e_shnum);
if (section_headers.size() != header.e_shnum)
return 0;
@@ -861,12 +1388,19 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
}
}
- if (header.sh_type == SHT_NOTE && !uuid.IsValid())
+ // Process ELF note section entries.
+ if (header.sh_type == SHT_NOTE)
{
+ // Allow notes to refine module info.
DataExtractor data;
if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size))
{
- ParseNoteGNUBuildID (data, uuid);
+ Error error = RefineModuleDetailsFromNote (data, arch_spec, uuid);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("ObjectFileELF::%s ELF note processing failed: %s", __FUNCTION__, error.AsCString ());
+ }
}
}
}
@@ -912,7 +1446,7 @@ ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id)
size_t
ObjectFileELF::ParseSectionHeaders()
{
- return GetSectionHeaderInfo(m_section_headers, m_data, m_header, m_uuid, m_gnu_debuglink_file, m_gnu_debuglink_crc);
+ return GetSectionHeaderInfo(m_section_headers, m_data, m_header, m_uuid, m_gnu_debuglink_file, m_gnu_debuglink_crc, m_arch_spec);
}
const ObjectFileELF::ELFSectionHeaderInfo *
@@ -1026,6 +1560,9 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
break;
}
+ elf::elf_xword log2align = (header.sh_addralign==0)
+ ? 0
+ : llvm::Log2_64(header.sh_addralign);
SectionSP section_sp (new Section(GetModule(), // Module to which this section belongs.
this, // ObjectFile to which this section belongs and should read section data from.
SectionIndex(I), // Section ID.
@@ -1035,6 +1572,7 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
vm_size, // VM size in bytes of this section.
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.
if (is_thread_specific)
@@ -1117,8 +1655,9 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
- // No need to add symbols that have no names
- if (symbol_name == NULL || symbol_name[0] == '\0')
+ // No need to add non-section symbols that have no names
+ if (symbol.getType() != STT_SECTION &&
+ (symbol_name == NULL || symbol_name[0] == '\0'))
continue;
//symbol.Dump (&strm, i, &strtab_data, section_list);
@@ -1228,7 +1767,7 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
}
uint64_t symbol_value = symbol.st_value;
- if (symbol_section_sp)
+ 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;
@@ -1279,7 +1818,6 @@ ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id, lldb_p
user_id_t strtab_id = symtab_hdr->sh_link + 1;
Section *strtab = section_list->FindSectionByID(strtab_id).get();
- unsigned num_symbols = 0;
if (symtab && strtab)
{
assert (symtab->GetObjectFile() == this);
@@ -1292,13 +1830,12 @@ ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id, lldb_p
{
size_t num_symbols = symtab_data.GetByteSize() / symtab_hdr->sh_entsize;
- num_symbols = ParseSymbols(symbol_table, start_id,
- section_list, num_symbols,
- symtab_data, strtab_data);
+ return ParseSymbols(symbol_table, start_id, section_list,
+ num_symbols, symtab_data, strtab_data);
}
}
- return num_symbols;
+ return 0;
}
size_t
@@ -1526,6 +2063,136 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,
strtab_data);
}
+unsigned
+ObjectFileELF::RelocateSection(Symtab* symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr,
+ const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr,
+ DataExtractor &rel_data, DataExtractor &symtab_data,
+ DataExtractor &debug_data, Section* rel_section)
+{
+ ELFRelocation rel(rel_hdr->sh_type);
+ lldb::addr_t offset = 0;
+ const unsigned num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
+ typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
+ reloc_info_fn reloc_type;
+ reloc_info_fn reloc_symbol;
+
+ if (hdr->Is32Bit())
+ {
+ reloc_type = ELFRelocation::RelocType32;
+ reloc_symbol = ELFRelocation::RelocSymbol32;
+ }
+ else
+ {
+ reloc_type = ELFRelocation::RelocType64;
+ reloc_symbol = ELFRelocation::RelocSymbol64;
+ }
+
+ for (unsigned i = 0; i < num_relocations; ++i)
+ {
+ if (rel.Parse(rel_data, &offset) == false)
+ break;
+
+ Symbol* symbol = NULL;
+
+ if (hdr->Is32Bit())
+ {
+ switch (reloc_type(rel)) {
+ case R_386_32:
+ case R_386_PC32:
+ default:
+ assert(false && "unexpected relocation type");
+ }
+ } else {
+ switch (reloc_type(rel)) {
+ case R_X86_64_64:
+ {
+ symbol = symtab->FindSymbolByID(reloc_symbol(rel));
+ if (symbol)
+ {
+ addr_t value = symbol->GetAddress().GetFileAddress();
+ DataBufferSP& data_buffer_sp = debug_data.GetSharedDataBuffer();
+ uint64_t* dst = reinterpret_cast<uint64_t*>(data_buffer_sp->GetBytes() + rel_section->GetFileOffset() + ELFRelocation::RelocOffset64(rel));
+ *dst = value + ELFRelocation::RelocAddend64(rel);
+ }
+ break;
+ }
+ case R_X86_64_32:
+ case R_X86_64_32S:
+ {
+ symbol = symtab->FindSymbolByID(reloc_symbol(rel));
+ if (symbol)
+ {
+ addr_t value = symbol->GetAddress().GetFileAddress();
+ value += ELFRelocation::RelocAddend32(rel);
+ assert((reloc_type(rel) == R_X86_64_32 && (value <= UINT32_MAX)) ||
+ (reloc_type(rel) == R_X86_64_32S &&
+ ((int64_t)value <= INT32_MAX && (int64_t)value >= INT32_MIN)));
+ uint32_t truncated_addr = (value & 0xFFFFFFFF);
+ DataBufferSP& data_buffer_sp = debug_data.GetSharedDataBuffer();
+ uint32_t* dst = reinterpret_cast<uint32_t*>(data_buffer_sp->GetBytes() + rel_section->GetFileOffset() + ELFRelocation::RelocOffset32(rel));
+ *dst = truncated_addr;
+ }
+ break;
+ }
+ case R_X86_64_PC32:
+ default:
+ assert(false && "unexpected relocation type");
+ }
+ }
+ }
+
+ return 0;
+}
+
+unsigned
+ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr, user_id_t rel_id)
+{
+ assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);
+
+ // Parse in the section list if needed.
+ SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return 0;
+
+ // Section ID's are ones based.
+ user_id_t symtab_id = rel_hdr->sh_link + 1;
+ user_id_t debug_id = rel_hdr->sh_info + 1;
+
+ const ELFSectionHeader *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
+ if (!symtab_hdr)
+ return 0;
+
+ const ELFSectionHeader *debug_hdr = GetSectionHeaderByIndex(debug_id);
+ if (!debug_hdr)
+ return 0;
+
+ Section *rel = section_list->FindSectionByID(rel_id).get();
+ if (!rel)
+ return 0;
+
+ Section *symtab = section_list->FindSectionByID(symtab_id).get();
+ if (!symtab)
+ return 0;
+
+ Section *debug = section_list->FindSectionByID(debug_id).get();
+ if (!debug)
+ return 0;
+
+ DataExtractor rel_data;
+ DataExtractor symtab_data;
+ DataExtractor debug_data;
+
+ if (ReadSectionData(rel, rel_data) &&
+ ReadSectionData(symtab, symtab_data) &&
+ ReadSectionData(debug, debug_data))
+ {
+ RelocateSection(m_symtab_ap.get(), &m_header, rel_hdr, symtab_hdr, debug_hdr,
+ rel_data, symtab_data, debug_data, debug);
+ }
+
+ return 0;
+}
+
Symtab *
ObjectFileELF::GetSymtab()
{
@@ -1588,6 +2255,25 @@ ObjectFileELF::GetSymtab()
}
}
}
+
+ for (SectionHeaderCollIter I = m_section_headers.begin();
+ I != m_section_headers.end(); ++I)
+ {
+ if (I->sh_type == SHT_RELA || I->sh_type == SHT_REL)
+ {
+ if (CalculateType() == eTypeObjectFile)
+ {
+ const char *section_name = I->section_name.AsCString("");
+ if (strstr(section_name, ".rela.debug") ||
+ strstr(section_name, ".rel.debug"))
+ {
+ const ELFSectionHeader &reloc_header = *I;
+ user_id_t reloc_id = SectionIndex(I);
+ RelocateDebugSections(&reloc_header, reloc_id);
+ }
+ }
+ }
+ }
return m_symtab_ap.get();
}
@@ -1958,9 +2644,13 @@ ObjectFileELF::GetArchitecture (ArchSpec &arch)
if (!ParseHeader())
return false;
- arch.SetArchitecture (eArchTypeELF, m_header.e_machine, LLDB_INVALID_CPUTYPE);
- arch.GetTriple().setOSName (Host::GetOSString().GetCString());
- arch.GetTriple().setVendorName(Host::GetVendorString().GetCString());
+ if (m_section_headers.empty())
+ {
+ // Allow elf notes to be parsed which may affect the detected architecture.
+ ParseSectionHeaders();
+ }
+
+ arch = m_arch_spec;
return true;
}
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 9b7c073d902d..6b036af7aeff 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -17,6 +17,7 @@
#include "lldb/Host/FileSpec.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Core/UUID.h"
+#include "lldb/Core/ArchSpec.h"
#include "ELFHeader.h"
@@ -191,6 +192,11 @@ private:
lldb::offset_t offset,
lldb::offset_t length);
+ ObjectFileELF (const lldb::ModuleSP &module_sp,
+ lldb::DataBufferSP& data_sp,
+ const lldb::ProcessSP &process_sp,
+ lldb::addr_t header_addr);
+
typedef std::vector<elf::ELFProgramHeader> ProgramHeaderColl;
typedef ProgramHeaderColl::iterator ProgramHeaderCollIter;
typedef ProgramHeaderColl::const_iterator ProgramHeaderCollConstIter;
@@ -209,6 +215,7 @@ private:
/// Version of this reader common to all plugins based on this class.
static const uint32_t m_plugin_version = 1;
+ static const uint32_t g_core_uuid_magic;
/// ELF file header.
elf::ELFHeader m_header;
@@ -236,6 +243,9 @@ private:
/// Cached value of the entry point for this module.
lldb_private::Address m_entry_point_address;
+ /// The architecture detected from parsing elf file contents.
+ lldb_private::ArchSpec m_arch_spec;
+
/// Returns a 1 based index of the given section header.
size_t
SectionIndex(const SectionHeaderCollIter &I);
@@ -244,6 +254,17 @@ private:
size_t
SectionIndex(const SectionHeaderCollConstIter &I) const;
+ // Parses the ELF program headers.
+ static size_t
+ GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
+ lldb_private::DataExtractor &data,
+ const elf::ELFHeader &header);
+
+ // Finds PT_NOTE segments and calculates their crc sum.
+ static uint32_t
+ CalculateELFNotesSegmentsCRC32(const ProgramHeaderColl& program_headers,
+ lldb_private::DataExtractor &data);
+
/// Parses all section headers present in this object file and populates
/// m_program_headers. This method will compute the header list only once.
/// Returns the number of headers parsed.
@@ -256,14 +277,15 @@ private:
size_t
ParseSectionHeaders();
- /// Parses the elf section headers and returns the uuid, debug link name, crc.
+ /// Parses the elf section headers and returns the uuid, debug link name, crc, archspec.
static size_t
GetSectionHeaderInfo(SectionHeaderColl &section_headers,
lldb_private::DataExtractor &data,
const elf::ELFHeader &header,
lldb_private::UUID &uuid,
std::string &gnu_debuglink_file,
- uint32_t &gnu_debuglink_crc);
+ uint32_t &gnu_debuglink_crc,
+ lldb_private::ArchSpec &arch_spec);
/// Scans the dynamic section and locates all dependent modules (shared
/// libraries) populating m_filespec_ap. This method will compute the
@@ -303,6 +325,32 @@ private:
const ELFSectionHeaderInfo *rela_hdr,
lldb::user_id_t section_id);
+ /// Relocates debug sections
+ unsigned
+ RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr, lldb::user_id_t rel_id);
+
+ unsigned
+ RelocateSection(lldb_private::Symtab* symtab, const elf::ELFHeader *hdr, const elf::ELFSectionHeader *rel_hdr,
+ const elf::ELFSectionHeader *symtab_hdr, const elf::ELFSectionHeader *debug_hdr,
+ lldb_private::DataExtractor &rel_data, lldb_private::DataExtractor &symtab_data,
+ lldb_private::DataExtractor &debug_data, lldb_private::Section* rel_section);
+
+ /// Loads the section name string table into m_shstr_data. Returns the
+ /// number of bytes constituting the table.
+ size_t
+ GetSectionHeaderStringTable();
+
+ /// Utility method for looking up a section given its name. Returns the
+ /// index of the corresponding section or zero if no section with the given
+ /// name can be found (note that section indices are always 1 based, and so
+ /// section index 0 is never valid).
+ lldb::user_id_t
+ GetSectionIndexByName(const char *name);
+
+ // Returns the ID of the first section that has the given type.
+ lldb::user_id_t
+ GetSectionIndexByType(unsigned type);
+
/// Returns the section header with the given id or NULL.
const ELFSectionHeaderInfo *
GetSectionHeaderByIndex(lldb::user_id_t id);
@@ -364,6 +412,9 @@ private:
unsigned
PLTRelocationType();
+
+ static lldb_private::Error
+ RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch_spec, lldb_private::UUID &uuid);
};
#endif // #ifndef liblldb_ObjectFileELF_h_
diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
new file mode 100644
index 000000000000..5498bed13ebc
--- /dev/null
+++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
@@ -0,0 +1,363 @@
+//===-- ObjectFileJIT.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+
+#include "ObjectFileJIT.h"
+
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RangeMap.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Core/UUID.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Platform.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/Target.h"
+
+#ifndef __APPLE__
+#include "Utility/UuidCompatibility.h"
+#endif
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+void
+ObjectFileJIT::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ CreateInstance,
+ CreateMemoryInstance,
+ GetModuleSpecifications);
+}
+
+void
+ObjectFileJIT::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+lldb_private::ConstString
+ObjectFileJIT::GetPluginNameStatic()
+{
+ static ConstString g_name("jit");
+ return g_name;
+}
+
+const char *
+ObjectFileJIT::GetPluginDescriptionStatic()
+{
+ return "JIT code object file";
+}
+
+ObjectFile *
+ObjectFileJIT::CreateInstance (const lldb::ModuleSP &module_sp,
+ DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ const FileSpec* file,
+ lldb::offset_t file_offset,
+ lldb::offset_t length)
+{
+ // JIT'ed object file is backed by the ObjectFileJITDelegate, never
+ // read from a file
+ return NULL;
+}
+
+ObjectFile *
+ObjectFileJIT::CreateMemoryInstance (const lldb::ModuleSP &module_sp,
+ DataBufferSP& data_sp,
+ const ProcessSP &process_sp,
+ lldb::addr_t header_addr)
+{
+ // JIT'ed object file is backed by the ObjectFileJITDelegate, never
+ // read from memory
+ return NULL;
+}
+
+size_t
+ObjectFileJIT::GetModuleSpecifications (const lldb_private::FileSpec& file,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs)
+{
+ // JIT'ed object file can't be read from a file on disk
+ return 0;
+}
+
+ObjectFileJIT::ObjectFileJIT (const lldb::ModuleSP &module_sp,
+ const ObjectFileJITDelegateSP &delegate_sp) :
+ ObjectFile(module_sp, NULL, 0, 0, DataBufferSP(), 0),
+ m_delegate_wp ()
+{
+ if (delegate_sp)
+ {
+ m_delegate_wp = delegate_sp;
+ m_data.SetByteOrder(delegate_sp->GetByteOrder());
+ m_data.SetAddressByteSize(delegate_sp->GetAddressByteSize());
+ }
+}
+
+ObjectFileJIT::~ObjectFileJIT()
+{
+}
+
+
+bool
+ObjectFileJIT::ParseHeader ()
+{
+ // JIT code is never in a file, nor is it required to have any header
+ return false;
+}
+
+ByteOrder
+ObjectFileJIT::GetByteOrder () const
+{
+ return m_data.GetByteOrder();
+}
+
+bool
+ObjectFileJIT::IsExecutable() const
+{
+ return false;
+}
+
+uint32_t
+ObjectFileJIT::GetAddressByteSize () const
+{
+ return m_data.GetAddressByteSize();
+}
+
+
+Symtab *
+ObjectFileJIT::GetSymtab()
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_symtab_ap.get() == NULL)
+ {
+ m_symtab_ap.reset(new Symtab(this));
+ Mutex::Locker symtab_locker (m_symtab_ap->GetMutex());
+ ObjectFileJITDelegateSP delegate_sp (m_delegate_wp.lock());
+ if (delegate_sp)
+ delegate_sp->PopulateSymtab(this, *m_symtab_ap);
+ // TODO: get symbols from delegate
+ m_symtab_ap->Finalize ();
+ }
+ }
+ return m_symtab_ap.get();
+}
+
+bool
+ObjectFileJIT::IsStripped ()
+{
+ return false; // JIT code that is in a module is never stripped
+}
+
+void
+ObjectFileJIT::CreateSections (SectionList &unified_section_list)
+{
+ if (!m_sections_ap.get())
+ {
+ m_sections_ap.reset(new SectionList());
+ ObjectFileJITDelegateSP delegate_sp (m_delegate_wp.lock());
+ if (delegate_sp)
+ {
+ delegate_sp->PopulateSectionList(this, *m_sections_ap);
+ unified_section_list = *m_sections_ap;
+ }
+ }
+}
+
+void
+ObjectFileJIT::Dump (Stream *s)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ s->Printf("%p: ", static_cast<void*>(this));
+ s->Indent();
+ s->PutCString("ObjectFileJIT");
+
+ ArchSpec arch;
+ if (GetArchitecture(arch))
+ *s << ", arch = " << arch.GetArchitectureName();
+
+ s->EOL();
+
+ SectionList *sections = GetSectionList();
+ if (sections)
+ sections->Dump(s, NULL, true, UINT32_MAX);
+
+ if (m_symtab_ap.get())
+ m_symtab_ap->Dump(s, NULL, eSortOrderNone);
+ }
+}
+
+bool
+ObjectFileJIT::GetUUID (lldb_private::UUID* uuid)
+{
+ // TODO: maybe get from delegate, not needed for first pass
+ return false;
+}
+
+
+uint32_t
+ObjectFileJIT::GetDependentModules (FileSpecList& files)
+{
+ // JIT modules don't have dependencies, but they could
+ // if external functions are called and we know where they are
+ files.Clear();
+ return 0;
+}
+
+lldb_private::Address
+ObjectFileJIT::GetEntryPointAddress ()
+{
+ return Address();
+}
+
+lldb_private::Address
+ObjectFileJIT::GetHeaderAddress ()
+{
+ return Address();
+}
+
+
+
+ObjectFile::Type
+ObjectFileJIT::CalculateType()
+{
+ return eTypeJIT;
+}
+
+ObjectFile::Strata
+ObjectFileJIT::CalculateStrata()
+{
+ return eStrataJIT;
+}
+
+
+bool
+ObjectFileJIT::GetArchitecture (ArchSpec &arch)
+{
+ ObjectFileJITDelegateSP delegate_sp (m_delegate_wp.lock());
+ if (delegate_sp)
+ return delegate_sp->GetArchitecture(arch);
+ return false;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ObjectFileJIT::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ObjectFileJIT::GetPluginVersion()
+{
+ return 1;
+}
+
+
+bool
+ObjectFileJIT::SetLoadAddress (Target &target,
+ lldb::addr_t value,
+ bool value_is_offset)
+{
+ size_t num_loaded_sections = 0;
+ SectionList *section_list = GetSectionList ();
+ if (section_list)
+ {
+ const size_t num_sections = section_list->GetSize();
+ // "value" is an offset to apply to each top level segment
+ for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx)
+ {
+ // Iterate through the object file sections to find all
+ // of the sections that size on disk (to avoid __PAGEZERO)
+ // and load them
+ SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
+ if (section_sp &&
+ section_sp->GetFileSize() > 0 &&
+ section_sp->IsThreadSpecific() == false)
+ {
+ if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() + value))
+ ++num_loaded_sections;
+ }
+ }
+ }
+ return num_loaded_sections > 0;
+}
+
+
+size_t
+ObjectFileJIT::ReadSectionData (const lldb_private::Section *section,
+ lldb::offset_t section_offset,
+ void *dst,
+ size_t dst_len) const
+{
+ lldb::offset_t file_size = section->GetFileSize();
+ if (section_offset < file_size)
+ {
+ size_t src_len = file_size - section_offset;
+ if (src_len > dst_len)
+ src_len = dst_len;
+ const uint8_t *src = ((uint8_t *)(uintptr_t)section->GetFileOffset()) + section_offset;
+
+ memcpy (dst, src, src_len);
+ return src_len;
+ }
+ return 0;
+}
+
+size_t
+ObjectFileJIT::ReadSectionData (const lldb_private::Section *section,
+ lldb_private::DataExtractor& section_data) const
+{
+ if (section->GetFileSize())
+ {
+ const void *src = (void *)(uintptr_t)section->GetFileOffset();
+
+ DataBufferSP data_sp (new lldb_private::DataBufferHeap(src, section->GetFileSize()));
+ if (data_sp)
+ {
+ section_data.SetData (data_sp, 0, data_sp->GetByteSize());
+ section_data.SetByteOrder (GetByteOrder());
+ section_data.SetAddressByteSize (GetAddressByteSize());
+ return section_data.GetByteSize();
+ }
+ }
+ section_data.Clear();
+ return 0;
+}
+
diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
new file mode 100644
index 000000000000..47140f5bcaff
--- /dev/null
+++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
@@ -0,0 +1,142 @@
+//===-- ObjectFileJIT.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_ObjectFileJIT_h_
+#define liblldb_ObjectFileJIT_h_
+
+#include "lldb/Core/Address.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+
+//----------------------------------------------------------------------
+// This class needs to be hidden as eventually belongs in a plugin that
+// will export the ObjectFile protocol
+//----------------------------------------------------------------------
+class ObjectFileJIT :
+ public lldb_private::ObjectFile
+{
+public:
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ static lldb_private::ObjectFile *
+ CreateInstance (const lldb::ModuleSP &module_sp,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ const lldb_private::FileSpec* file,
+ lldb::offset_t file_offset,
+ lldb::offset_t length);
+
+ static lldb_private::ObjectFile *
+ CreateMemoryInstance (const lldb::ModuleSP &module_sp,
+ lldb::DataBufferSP& data_sp,
+ const lldb::ProcessSP &process_sp,
+ lldb::addr_t header_addr);
+
+ static size_t
+ GetModuleSpecifications (const lldb_private::FileSpec& file,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs);
+
+ //------------------------------------------------------------------
+ // Member Functions
+ //------------------------------------------------------------------
+ ObjectFileJIT (const lldb::ModuleSP &module_sp,
+ const lldb::ObjectFileJITDelegateSP &delegate_sp);
+
+ virtual
+ ~ObjectFileJIT();
+
+ virtual bool
+ ParseHeader ();
+
+ virtual bool
+ SetLoadAddress(lldb_private::Target &target,
+ lldb::addr_t value,
+ bool value_is_offset);
+
+ virtual lldb::ByteOrder
+ GetByteOrder () const;
+
+ virtual bool
+ IsExecutable () const;
+
+ virtual uint32_t
+ GetAddressByteSize () const;
+
+ virtual lldb_private::Symtab *
+ GetSymtab();
+
+ virtual bool
+ IsStripped ();
+
+ virtual void
+ CreateSections (lldb_private::SectionList &unified_section_list);
+
+ virtual void
+ Dump (lldb_private::Stream *s);
+
+ virtual bool
+ GetArchitecture (lldb_private::ArchSpec &arch);
+
+ virtual bool
+ GetUUID (lldb_private::UUID* uuid);
+
+ virtual uint32_t
+ GetDependentModules (lldb_private::FileSpecList& files);
+
+ virtual size_t
+ ReadSectionData (const lldb_private::Section *section,
+ lldb::offset_t section_offset,
+ void *dst,
+ size_t dst_len) const;
+ virtual size_t
+ ReadSectionData (const lldb_private::Section *section,
+ lldb_private::DataExtractor& section_data) const;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual lldb_private::ConstString
+ GetPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+ virtual lldb_private::Address
+ GetEntryPointAddress ();
+
+ virtual lldb_private::Address
+ GetHeaderAddress ();
+
+ virtual ObjectFile::Type
+ CalculateType();
+
+ virtual ObjectFile::Strata
+ CalculateStrata();
+protected:
+ lldb::ObjectFileJITDelegateWP m_delegate_wp;
+};
+
+#endif // liblldb_ObjectFileJIT_h_
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index 7eca67ac7f57..7aa940a530b4 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -1,4 +1,4 @@
-//===-- PlatformFreeBSD.cpp ---------------------------------------*- C++ -*-===//
+//===-- PlatformFreeBSD.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -27,6 +27,7 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
using namespace lldb;
using namespace lldb_private;
@@ -47,10 +48,10 @@ PlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
case llvm::Triple::PC:
create = true;
break;
-
+
#if defined(__FreeBSD__) || defined(__OpenBSD__)
// Only accept "unknown" for the vendor if the host is BSD and
- // it "unknown" wasn't specified (it was just returned becasue it
+ // it "unknown" wasn't specified (it was just returned because it
// was NOT specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
@@ -59,7 +60,7 @@ PlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
default:
break;
}
-
+
if (create)
{
switch (triple.getOS())
@@ -67,10 +68,10 @@ PlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
case llvm::Triple::FreeBSD:
case llvm::Triple::KFreeBSD:
break;
-
+
#if defined(__FreeBSD__) || defined(__OpenBSD__)
// Only accept "unknown" for the OS if the host is BSD and
- // it "unknown" wasn't specified (it was just returned becasue it
+ // it "unknown" wasn't specified (it was just returned because it
// was NOT specified)
case llvm::Triple::UnknownOS:
create = arch->TripleOSWasSpecified();
@@ -122,7 +123,7 @@ PlatformFreeBSD::Initialize ()
#if defined (__FreeBSD__)
// Force a host flag to true for the default platform object.
PlatformSP default_platform_sp (new PlatformFreeBSD(true));
- default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
+ default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
Platform::SetDefaultPlatform (default_platform_sp);
#endif
PluginManager::RegisterPlugin(PlatformFreeBSD::GetPluginNameStatic(false),
@@ -186,10 +187,10 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
{
Error error;
// Nothing special to do here, just use the actual file and architecture
-
+
char exe_path[PATH_MAX];
FileSpec resolved_exe_file (exe_file);
-
+
if (IsHost())
{
// If we have "ls" as the exe_file, resolve the executable location based on
@@ -199,10 +200,10 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
exe_file.GetPath(exe_path, sizeof(exe_path));
resolved_exe_file.SetFile(exe_path, true);
}
-
+
if (!resolved_exe_file.Exists())
resolved_exe_file.ResolveExecutableLocation ();
-
+
if (resolved_exe_file.Exists())
error.Clear();
else
@@ -223,10 +224,10 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
else
{
// 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);
-
+
if (resolved_exe_file.Exists()) {
error.Clear();
}
@@ -248,7 +249,7 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
module_search_paths_ptr,
NULL,
NULL);
-
+
if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
{
exe_module_sp.reset();
@@ -279,18 +280,25 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
else
error.SetErrorToGenericError();
}
-
+
if (idx > 0)
arch_names.PutCString (", ");
arch_names.PutCString (platform_arch.GetArchitectureName());
}
-
+
if (error.Fail() || !exe_module_sp)
{
- error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
- exe_file.GetPath().c_str(),
- GetPluginName().GetCString(),
- arch_names.GetString().c_str());
+ if (exe_file.Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ exe_file.GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", exe_file.GetPath().c_str());
+ }
}
}
}
@@ -305,15 +313,13 @@ PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite
const uint8_t *trap_opcode = NULL;
size_t trap_opcode_size = 0;
- switch (arch.GetCore())
+ switch (arch.GetMachine())
{
default:
assert(false && "Unhandled architecture in PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode()");
break;
-
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_64_x86_64:
- case ArchSpec::eCore_x86_64_x86_64h:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
{
static const uint8_t g_i386_opcode[] = { 0xCC };
trap_opcode = g_i386_opcode;
@@ -451,7 +457,7 @@ PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_i
{
success = Platform::GetProcessInfo (pid, process_info);
}
- else if (m_remote_platform_sp)
+ else if (m_remote_platform_sp)
{
success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
}
@@ -633,19 +639,19 @@ PlatformFreeBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
// From macosx;s plugin code. For FreeBSD we may want to support more archs.
if (idx == 0)
{
- arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
+ arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
return arch.IsValid();
}
else if (idx == 1)
{
- ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
- ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
+ ArchSpec platform_arch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
+ ArchSpec platform_arch64(HostInfo::GetArchitecture(HostInfo::eArchKind64));
if (platform_arch.IsExactMatch(platform_arch64))
{
// This freebsd platform supports both 32 and 64 bit. Since we already
// returned the 64 bit arch for idx == 0, return the 32 bit arch
// for idx == 1
- arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
+ arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
return arch.IsValid();
}
}
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
index 0682eacc5a43..62958a08a9e0 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
@@ -1,4 +1,4 @@
-//===-- PlatformFreeBSD.h -----------------------------------------*- C++ -*-===//
+//===-- PlatformFreeBSD.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index bb07d999c4c2..cc4c693e1b43 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -18,8 +18,11 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/File.h"
+#include "lldb/Host/FileCache.h"
#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
using namespace lldb;
using namespace lldb_private;
@@ -57,6 +60,16 @@ PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpret
return m_options.get();
}
+bool
+PlatformPOSIX::IsConnected () const
+{
+ if (IsHost())
+ return true;
+ else if (m_remote_platform_sp)
+ return m_remote_platform_sp->IsConnected();
+ return false;
+}
+
lldb_private::Error
PlatformPOSIX::RunShellCommand (const char *command, // Shouldn't be NULL
const char *working_dir, // Pass NULL to use the current working directory
@@ -98,7 +111,7 @@ Error
PlatformPOSIX::SetFilePermissions (const char *path, uint32_t file_permissions)
{
if (m_remote_platform_sp)
- return m_remote_platform_sp->MakeDirectory(path, file_permissions);
+ return m_remote_platform_sp->SetFilePermissions(path, file_permissions);
else
return Platform::SetFilePermissions(path ,file_permissions);
}
@@ -110,7 +123,7 @@ PlatformPOSIX::OpenFile (const FileSpec& file_spec,
Error &error)
{
if (IsHost())
- return Host::OpenFile(file_spec, flags, mode, error);
+ return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error);
else if (m_remote_platform_sp)
return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error);
else
@@ -121,7 +134,7 @@ bool
PlatformPOSIX::CloseFile (lldb::user_id_t fd, Error &error)
{
if (IsHost())
- return Host::CloseFile(fd, error);
+ return FileCache::GetInstance().CloseFile(fd, error);
else if (m_remote_platform_sp)
return m_remote_platform_sp->CloseFile(fd, error);
else
@@ -136,7 +149,7 @@ PlatformPOSIX::ReadFile (lldb::user_id_t fd,
Error &error)
{
if (IsHost())
- return Host::ReadFile(fd, offset, dst, dst_len, error);
+ return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error);
else if (m_remote_platform_sp)
return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error);
else
@@ -151,7 +164,7 @@ PlatformPOSIX::WriteFile (lldb::user_id_t fd,
Error &error)
{
if (IsHost())
- return Host::WriteFile(fd, offset, src, src_len, error);
+ return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error);
else if (m_remote_platform_sp)
return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error);
else
@@ -339,7 +352,7 @@ lldb::user_id_t
PlatformPOSIX::GetFileSize (const FileSpec& file_spec)
{
if (IsHost())
- return Host::GetFileSize(file_spec);
+ return FileSystem::GetFileSize(file_spec);
else if (m_remote_platform_sp)
return m_remote_platform_sp->GetFileSize(file_spec);
else
@@ -350,7 +363,7 @@ Error
PlatformPOSIX::CreateSymlink(const char *src, const char *dst)
{
if (IsHost())
- return Host::Symlink(src, dst);
+ return FileSystem::Symlink(src, dst);
else if (m_remote_platform_sp)
return m_remote_platform_sp->CreateSymlink(src, dst);
else
@@ -372,7 +385,7 @@ Error
PlatformPOSIX::Unlink (const char *path)
{
if (IsHost())
- return Host::Unlink (path);
+ return FileSystem::Unlink(path);
else if (m_remote_platform_sp)
return m_remote_platform_sp->Unlink(path);
else
@@ -469,10 +482,9 @@ PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path
if (permissions == 0)
permissions = lldb::eFilePermissionsFileDefault;
- user_id_t fd_dst = Host::OpenFile(destination,
- File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
- permissions,
- error);
+ user_id_t fd_dst = FileCache::GetInstance().OpenFile(
+ destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, permissions,
+ error);
if (fd_dst == UINT64_MAX)
{
@@ -496,15 +508,11 @@ PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path
break;
if (n_read == 0)
break;
- if (Host::WriteFile(fd_dst,
- offset,
- buffer_sp->GetBytes(),
- n_read,
- error) != n_read)
+ if (FileCache::GetInstance().WriteFile(fd_dst, offset, buffer_sp->GetBytes(), n_read, error) != n_read)
{
if (!error.Fail())
error.SetErrorString("unable to write to destination file");
- break;
+ break;
}
offset += n_read;
}
@@ -513,7 +521,7 @@ PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path
if (fd_src != UINT64_MAX)
CloseFile(fd_src, error);
// And close the dst file descriptot.
- if (fd_dst != UINT64_MAX && !Host::CloseFile(fd_dst, error))
+ if (fd_dst != UINT64_MAX && !FileCache::GetInstance().CloseFile(fd_dst, error))
{
if (!error.Fail())
error.SetErrorString("unable to close destination file");
@@ -589,6 +597,176 @@ PlatformPOSIX::SetRemoteWorkingDirectory(const lldb_private::ConstString &path)
return Platform::SetRemoteWorkingDirectory(path);
}
+bool
+PlatformPOSIX::GetRemoteOSVersion ()
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetOSVersion (m_major_os_version,
+ m_minor_os_version,
+ m_update_os_version);
+ return false;
+}
+
+bool
+PlatformPOSIX::GetRemoteOSBuildString (std::string &s)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteOSBuildString (s);
+ s.clear();
+ return false;
+}
+
+bool
+PlatformPOSIX::GetRemoteOSKernelDescription (std::string &s)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
+ s.clear();
+ return false;
+}
+
+// Remote Platform subclasses need to override this function
+ArchSpec
+PlatformPOSIX::GetRemoteSystemArchitecture ()
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteSystemArchitecture ();
+ return ArchSpec();
+}
+
+const char *
+PlatformPOSIX::GetHostname ()
+{
+ if (IsHost())
+ return Platform::GetHostname();
+
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetHostname ();
+ return NULL;
+}
+
+const char *
+PlatformPOSIX::GetUserName (uint32_t uid)
+{
+ // Check the cache in Platform in case we have already looked this uid up
+ const char *user_name = Platform::GetUserName(uid);
+ if (user_name)
+ return user_name;
+
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetUserName(uid);
+ return NULL;
+}
+
+const char *
+PlatformPOSIX::GetGroupName (uint32_t gid)
+{
+ const char *group_name = Platform::GetGroupName(gid);
+ if (group_name)
+ return group_name;
+
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetGroupName(gid);
+ return NULL;
+}
+
+Error
+PlatformPOSIX::ConnectRemote (Args& args)
+{
+ Error error;
+ if (IsHost())
+ {
+ error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
+ }
+ else
+ {
+ if (!m_remote_platform_sp)
+ m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
+
+ if (m_remote_platform_sp && error.Success())
+ error = m_remote_platform_sp->ConnectRemote (args);
+ else
+ error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
+
+ if (error.Fail())
+ m_remote_platform_sp.reset();
+ }
+
+ if (error.Success() && m_remote_platform_sp)
+ {
+ if (m_options.get())
+ {
+ OptionGroupOptions* options = m_options.get();
+ OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r');
+ OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s');
+ OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c');
+
+ if (m_rsync_options->m_rsync)
+ {
+ SetSupportsRSync(true);
+ SetRSyncOpts(m_rsync_options->m_rsync_opts.c_str());
+ SetRSyncPrefix(m_rsync_options->m_rsync_prefix.c_str());
+ SetIgnoresRemoteHostname(m_rsync_options->m_ignores_remote_hostname);
+ }
+ if (m_ssh_options->m_ssh)
+ {
+ SetSupportsSSH(true);
+ SetSSHOpts(m_ssh_options->m_ssh_opts.c_str());
+ }
+ SetLocalCacheDirectory(m_cache_options->m_cache_dir.c_str());
+ }
+ }
+
+ return error;
+}
+
+Error
+PlatformPOSIX::DisconnectRemote ()
+{
+ Error error;
+
+ if (IsHost())
+ {
+ error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ error = m_remote_platform_sp->DisconnectRemote ();
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return error;
+}
+
+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;
+
+ if (IsHost())
+ {
+ // We are going to hand this process off to debugserver which will be in charge of setting the exit status.
+ // 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);
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ process_sp = m_remote_platform_sp->DebugProcess (launch_info, debugger, target, listener, error);
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return process_sp;
+
+}
+
void
PlatformPOSIX::CalculateTrapHandlerSymbolNames ()
{
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 130c84bdface..374e36495d88 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -33,7 +33,16 @@ public:
//------------------------------------------------------------
virtual lldb_private::OptionGroupOptions*
GetConnectionOptions (lldb_private::CommandInterpreter& interpreter);
-
+
+ const char *
+ GetHostname () override;
+
+ const char *
+ GetUserName (uint32_t uid) override;
+
+ const char *
+ GetGroupName (uint32_t gid) override;
+
virtual lldb_private::Error
PutFile (const lldb_private::FileSpec& source,
const lldb_private::FileSpec& destination,
@@ -79,7 +88,22 @@ public:
virtual bool
SetRemoteWorkingDirectory(const lldb_private::ConstString &path);
-
+
+ bool
+ GetRemoteOSVersion () override;
+
+ bool
+ GetRemoteOSBuildString (std::string &s) override;
+
+ bool
+ GetRemoteOSKernelDescription (std::string &s) override;
+
+ lldb_private::ArchSpec
+ GetRemoteSystemArchitecture () override;
+
+ bool
+ IsConnected () const override;
+
virtual lldb_private::Error
RunShellCommand (const char *command, // Shouldn't be NULL
const char *working_dir, // Pass NULL to use the current working directory
@@ -103,6 +127,13 @@ public:
virtual lldb_private::Error
Unlink (const char *path);
+ 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();
@@ -114,6 +145,12 @@ public:
virtual void
CalculateTrapHandlerSymbolNames ();
+ lldb_private::Error
+ ConnectRemote (lldb_private::Args& args) override;
+
+ lldb_private::Error
+ DisconnectRemote () override;
+
protected:
std::unique_ptr<lldb_private::OptionGroupOptions> m_options;
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 3832265638db..05fbc5101278 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -12,11 +12,6 @@
#include "PlatformRemoteGDBServer.h"
#include "lldb/Host/Config.h"
-// C Includes
-#ifndef LLDB_DISABLE_POSIX
-#include <sys/sysctl.h>
-#endif
-
// C++ Includes
// Other libraries and framework includes
// Project includes
@@ -24,6 +19,7 @@
#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/PluginManager.h"
@@ -346,13 +342,18 @@ PlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &p
Error
PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
Error error;
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
-
+
+ if (log)
+ log->Printf ("PlatformRemoteGDBServer::%s() called", __FUNCTION__);
+
m_gdb_client.SetSTDIN ("/dev/null");
m_gdb_client.SetSTDOUT ("/dev/null");
m_gdb_client.SetSTDERR ("/dev/null");
m_gdb_client.SetDisableASLR (launch_info.GetFlags().Test (eLaunchFlagDisableASLR));
+ m_gdb_client.SetDetachOnError (launch_info.GetFlags().Test (eLaunchFlagDetachOnError));
const char *working_dir = launch_info.GetWorkingDirectory();
if (working_dir && working_dir[0])
@@ -377,7 +378,9 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
const char *arch_triple = arch_spec.GetTriple().str().c_str();
m_gdb_client.SendLaunchArchPacket(arch_triple);
-
+ if (log)
+ log->Printf ("PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", __FUNCTION__, arch_triple ? arch_triple : "<NULL>");
+
const uint32_t old_packet_timeout = m_gdb_client.SetPacketTimeout (5);
int arg_packet_err = m_gdb_client.SendArgumentsPacket (launch_info);
m_gdb_client.SetPacketTimeout (old_packet_timeout);
@@ -388,11 +391,23 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
{
pid = m_gdb_client.GetCurrentProcessID ();
if (pid != LLDB_INVALID_PROCESS_ID)
+ {
launch_info.SetProcessID (pid);
+ if (log)
+ log->Printf ("PlatformRemoteGDBServer::%s() pid %" PRIu64 " launched successfully", __FUNCTION__, pid);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("PlatformRemoteGDBServer::%s() launch succeeded but we didn't get a valid process id back!", __FUNCTION__);
+ // FIXME isn't this an error condition? Do we need to set an error here? Check with Greg.
+ }
}
else
{
error.SetErrorString (error_str.c_str());
+ if (log)
+ log->Printf ("PlatformRemoteGDBServer::%s() launch failed: %s", __FUNCTION__, error.AsCString ());
}
}
else
@@ -423,7 +438,7 @@ PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_i
// When remote debugging to iOS, we use a USB mux that always talks
// to localhost, so we will need the remote debugserver to accept connections
// only from localhost, no matter what our current hostname is
- port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, "localhost");
+ port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, "127.0.0.1");
}
else
{
@@ -511,7 +526,7 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
// When remote debugging to iOS, we use a USB mux that always talks
// to localhost, so we will need the remote debugserver to accept connections
// only from localhost, no matter what our current hostname is
- port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, "localhost");
+ port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, "127.0.0.1");
}
else
{
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
index d13b9a485858..4b488444de1e 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
@@ -22,12 +22,23 @@
#include "ProcessFreeBSD.h"
#include "ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
+#include "Plugins/Process/Utility/FreeBSDSignals.h"
#include "ProcessMonitor.h"
#include "FreeBSDThread.h"
using namespace lldb;
using namespace lldb_private;
+namespace
+{
+ UnixSignalsSP&
+ GetFreeBSDSignals ()
+ {
+ static UnixSignalsSP s_freebsd_signals_sp (new FreeBSDSignals ());
+ return s_freebsd_signals_sp;
+ }
+}
+
//------------------------------------------------------------------------------
// Static functions.
@@ -113,7 +124,8 @@ ProcessFreeBSD::EnablePluginLogging(Stream *strm, Args &command)
// Constructors and destructors.
ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener)
- : ProcessPOSIX(target, listener)
+ : ProcessPOSIX(target, listener, GetFreeBSDSignals ()),
+ m_resume_signo(0)
{
}
@@ -132,8 +144,6 @@ ProcessFreeBSD::DoDetach(bool keep_stopped)
return error;
}
- DisableAllBreakpointSites();
-
error = m_monitor->Detach(GetID());
if (error.Success())
@@ -147,9 +157,6 @@ ProcessFreeBSD::DoResume()
{
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
- // FreeBSD's ptrace() uses 0 to indicate "no signal is to be sent."
- int resume_signal = 0;
-
SetPrivateState(eStateRunning);
Mutex::Locker lock(m_thread_list.GetMutex());
@@ -172,11 +179,11 @@ ProcessFreeBSD::DoResume()
}
if (log)
- log->Printf("process %lu resuming (%s)", GetID(), do_step ? "step" : "continue");
+ log->Printf("process %" PRIu64 " resuming (%s)", GetID(), do_step ? "step" : "continue");
if (do_step)
- m_monitor->SingleStep(GetID(), resume_signal);
+ m_monitor->SingleStep(GetID(), m_resume_signo);
else
- m_monitor->Resume(GetID(), resume_signal);
+ m_monitor->Resume(GetID(), m_resume_signo);
return Error();
}
@@ -228,6 +235,7 @@ ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_th
Error
ProcessFreeBSD::WillResume()
{
+ m_resume_signo = 0;
m_suspend_tids.clear();
m_run_tids.clear();
m_step_tids.clear();
@@ -274,4 +282,3 @@ ProcessFreeBSD::SendMessage(const ProcessMessage &message)
m_message_queue.push(message);
}
-
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 3d793d0c1c20..63439b155111 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -702,7 +702,7 @@ EventMessageOperation::Execute(ProcessMonitor *monitor)
//------------------------------------------------------------------------------
/// @class KillOperation
-/// @brief Implements ProcessMonitor::BringProcessIntoLimbo.
+/// @brief Implements ProcessMonitor::Kill.
class KillOperation : public Operation
{
public:
@@ -727,7 +727,7 @@ KillOperation::Execute(ProcessMonitor *monitor)
//------------------------------------------------------------------------------
/// @class DetachOperation
-/// @brief Implements ProcessMonitor::BringProcessIntoLimbo.
+/// @brief Implements ProcessMonitor::Detach.
class DetachOperation : public Operation
{
public:
@@ -807,6 +807,7 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
const char *stdout_path,
const char *stderr_path,
const char *working_dir,
+ const lldb_private::ProcessLaunchInfo & /* launch_info */,
lldb_private::Error &error)
: m_process(static_cast<ProcessFreeBSD *>(process)),
m_operation_thread(LLDB_INVALID_HOST_THREAD),
@@ -1628,9 +1629,13 @@ ProcessMonitor::Resume(lldb::tid_t unused, uint32_t signo)
bool result;
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s", __FUNCTION__, GetPID(),
- m_process->GetUnixSignals().GetSignalAsCString (signo));
+ if (log) {
+ const char *signame = m_process->GetUnixSignals().GetSignalAsCString (signo);
+ if (signame == nullptr)
+ signame = "<none>";
+ log->Printf("ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s",
+ __FUNCTION__, GetPID(), signame);
+ }
ResumeOperation op(signo, result);
DoOperation(&op);
if (log)
@@ -1648,7 +1653,7 @@ ProcessMonitor::SingleStep(lldb::tid_t unused, uint32_t signo)
}
bool
-ProcessMonitor::BringProcessIntoLimbo()
+ProcessMonitor::Kill()
{
bool result;
KillOperation op(result);
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
index 4c8198fb2e4c..314743b00754 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -55,6 +55,7 @@ public:
const char *stdout_path,
const char *stderr_path,
const char *working_dir,
+ const lldb_private::ProcessLaunchInfo &launch_info,
lldb_private::Error &error);
ProcessMonitor(ProcessPOSIX *process,
@@ -194,11 +195,9 @@ public:
bool
SingleStep(lldb::tid_t unused, uint32_t signo);
- /// Sends the inferior process a PTRACE_KILL signal. The inferior will
- /// still exists and can be interrogated. Once resumed it will exit as
- /// though it received a SIGKILL.
+ /// Terminate the traced process.
bool
- BringProcessIntoLimbo();
+ Kill();
lldb_private::Error
Detach(lldb::tid_t tid);
diff --git a/source/Plugins/Process/POSIX/POSIXThread.cpp b/source/Plugins/Process/POSIX/POSIXThread.cpp
index cc759eaad96d..d48f8f9dd307 100644
--- a/source/Plugins/Process/POSIX/POSIXThread.cpp
+++ b/source/Plugins/Process/POSIX/POSIXThread.cpp
@@ -20,6 +20,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
@@ -29,8 +30,10 @@
#include "ProcessPOSIX.h"
#include "ProcessPOSIXLog.h"
#include "ProcessMonitor.h"
+#include "RegisterContextPOSIXProcessMonitor_arm64.h"
#include "RegisterContextPOSIXProcessMonitor_mips64.h"
#include "RegisterContextPOSIXProcessMonitor_x86.h"
+#include "RegisterContextLinux_arm64.h"
#include "RegisterContextLinux_i386.h"
#include "RegisterContextLinux_x86_64.h"
#include "RegisterContextFreeBSD_i386.h"
@@ -110,7 +113,7 @@ POSIXThread::RefreshStateAfterStop()
GetRegisterContext()->InvalidateIfNeeded (force);
}
// FIXME: This should probably happen somewhere else.
- SetResumeState(eStateRunning);
+ SetResumeState(eStateRunning, true);
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
if (log)
log->Printf ("POSIXThread::%s (tid = %" PRIi64 ") setting thread resume state to running", __FUNCTION__, GetID());
@@ -156,58 +159,82 @@ POSIXThread::GetRegisterContext()
RegisterInfoInterface *reg_interface = NULL;
const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture();
- switch (target_arch.GetCore())
+ switch (target_arch.GetTriple().getOS())
{
- case ArchSpec::eCore_mips64:
- {
- switch (target_arch.GetTriple().getOS())
+ case llvm::Triple::FreeBSD:
+ switch (target_arch.GetMachine())
{
- case llvm::Triple::FreeBSD:
+ case llvm::Triple::mips64:
reg_interface = new RegisterContextFreeBSD_mips64(target_arch);
break;
+ case llvm::Triple::x86:
+ reg_interface = new RegisterContextFreeBSD_i386(target_arch);
+ break;
+ case llvm::Triple::x86_64:
+ reg_interface = new RegisterContextFreeBSD_x86_64(target_arch);
+ break;
default:
- assert(false && "OS not supported");
break;
}
-
- if (reg_interface)
- {
- RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- }
break;
- }
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- case ArchSpec::eCore_x86_64_x86_64:
- {
- switch (target_arch.GetTriple().getOS())
+ case llvm::Triple::Linux:
+ switch (target_arch.GetMachine())
{
- case llvm::Triple::FreeBSD:
- reg_interface = new RegisterContextFreeBSD_x86_64(target_arch);
+ case llvm::Triple::aarch64:
+ assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host");
+ reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm64(target_arch));
break;
- case llvm::Triple::Linux:
- reg_interface = new RegisterContextLinux_x86_64(target_arch);
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
+ {
+ // 32-bit hosts run with a RegisterContextLinux_i386 context.
+ reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_i386(target_arch));
+ }
+ else
+ {
+ assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
+ "Register setting path assumes this is a 64-bit host");
+ // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context.
+ reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_x86_64(target_arch));
+ }
break;
default:
- assert(false && "OS not supported");
break;
}
- if (reg_interface)
+ default:
+ break;
+ }
+
+ assert(reg_interface && "OS or CPU not supported!");
+
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::aarch64:
+ {
+ RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
+ case llvm::Triple::mips64:
+ {
+ RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
{
RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface);
m_posix_thread = reg_ctx;
m_reg_context_sp.reset(reg_ctx);
+ break;
}
- break;
- }
-
default:
- assert(false && "CPU type not supported!");
break;
}
}
@@ -546,18 +573,14 @@ void
POSIXThread::SignalNotify(const ProcessMessage &message)
{
int signo = message.GetSignal();
-
SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
- SetResumeSignal(signo);
}
void
POSIXThread::SignalDeliveredNotify(const ProcessMessage &message)
{
int signo = message.GetSignal();
-
SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
- SetResumeSignal(signo);
}
void
@@ -576,7 +599,6 @@ POSIXThread::CrashNotify(const ProcessMessage &message)
SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo,
message.GetCrashReason(),
message.GetFaultAddress())));
- SetResumeSignal(signo);
}
void
@@ -589,19 +611,18 @@ unsigned
POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
{
unsigned reg = LLDB_INVALID_REGNUM;
- ArchSpec arch = Host::GetArchitecture();
+ ArchSpec arch = HostInfo::GetArchitecture();
- switch (arch.GetCore())
+ switch (arch.GetMachine())
{
default:
llvm_unreachable("CPU type not supported!");
break;
- case ArchSpec::eCore_mips64:
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- case ArchSpec::eCore_x86_64_x86_64:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::mips64:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
{
POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
reg = reg_ctx->GetRegisterIndexFromOffset(offset);
@@ -621,19 +642,18 @@ const char *
POSIXThread::GetRegisterName(unsigned reg)
{
const char * name = nullptr;
- ArchSpec arch = Host::GetArchitecture();
+ ArchSpec arch = HostInfo::GetArchitecture();
- switch (arch.GetCore())
+ switch (arch.GetMachine())
{
default:
assert(false && "CPU type not supported!");
break;
- case ArchSpec::eCore_mips64:
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- case ArchSpec::eCore_x86_64_x86_64:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::mips64:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
name = GetRegisterContext()->GetRegisterName(reg);
break;
}
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
index 62394623c59d..f340631c7d07 100644
--- a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -70,8 +70,8 @@ ProcessPOSIX::Initialize()
//------------------------------------------------------------------------------
// Constructors and destructors.
-ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener)
- : Process(target, listener),
+ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener, UnixSignalsSP &unix_signals_sp)
+ : Process(target, listener, unix_signals_sp),
m_byte_order(lldb::endian::InlHostByteOrder()),
m_monitor(NULL),
m_module(NULL),
@@ -176,23 +176,23 @@ ProcessPOSIX::WillLaunch(Module* module)
}
const char *
-ProcessPOSIX::GetFilePath(
- const lldb_private::ProcessLaunchInfo::FileAction *file_action,
- const char *default_path)
+ProcessPOSIX::GetFilePath(const lldb_private::FileAction *file_action, const char *default_path)
{
const char *pts_name = "/dev/pts/";
const char *path = NULL;
if (file_action)
{
- if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
+ if (file_action->GetAction() == FileAction::eFileActionOpen)
+ {
path = file_action->GetPath();
// By default the stdio paths passed in will be pseudo-terminal
// (/dev/pts). If so, convert to using a different default path
// instead to redirect I/O to the debugger console. This should
// also handle user overrides to /dev/null or a different file.
- if (::strncmp(path, pts_name, ::strlen(pts_name)) == 0)
+ if (!path || ::strncmp(path, pts_name, ::strlen(pts_name)) == 0)
path = default_path;
+ }
}
return path;
@@ -217,7 +217,7 @@ ProcessPOSIX::DoLaunch (Module *module,
SetPrivateState(eStateLaunching);
- const lldb_private::ProcessLaunchInfo::FileAction *file_action;
+ const lldb_private::FileAction *file_action;
// Default of NULL will mean to use existing open file descriptors
const char *stdin_path = NULL;
@@ -241,6 +241,7 @@ ProcessPOSIX::DoLaunch (Module *module,
stdout_path,
stderr_path,
working_dir,
+ launch_info,
error);
m_module = module;
@@ -335,11 +336,9 @@ ProcessPOSIX::DoDestroy()
if (!HasExited())
{
- // Drive the exit event to completion (do not keep the inferior in
- // limbo).
+ assert(m_monitor);
m_exit_now = true;
-
- if ((m_monitor == NULL || kill(m_monitor->GetPID(), SIGKILL)) && error.Success())
+ if (!m_monitor->Kill())
{
error.SetErrorToErrno();
return error;
@@ -379,6 +378,8 @@ ProcessPOSIX::DoDidExec()
void
ProcessPOSIX::SendMessage(const ProcessMessage &message)
{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
Mutex::Locker lock(m_message_mutex);
Mutex::Locker thread_lock(m_thread_list.GetMutex());
@@ -420,8 +421,14 @@ ProcessPOSIX::SendMessage(const ProcessMessage &message)
break;
case ProcessMessage::eExitMessage:
- assert(thread);
- thread->SetState(eStateExited);
+ if (thread != nullptr)
+ thread->SetState(eStateExited);
+ else
+ {
+ if (log)
+ log->Warning ("ProcessPOSIX::%s eExitMessage for TID %" PRIu64 " failed to find a thread to mark as eStateExited, ignoring", __FUNCTION__, message.GetTID ());
+ }
+
// FIXME: I'm not sure we need to do this.
if (message.GetTID() == GetID())
{
@@ -635,20 +642,26 @@ ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr)
size_t
ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
{
+ static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xD4 };
static const uint8_t g_i386_opcode[] = { 0xCC };
ArchSpec arch = GetTarget().GetArchitecture();
const uint8_t *opcode = NULL;
size_t opcode_size = 0;
- switch (arch.GetCore())
+ switch (arch.GetMachine())
{
default:
assert(false && "CPU type not supported!");
break;
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_64_x86_64:
+ case llvm::Triple::aarch64:
+ opcode = g_aarch64_opcode;
+ opcode_size = sizeof(g_aarch64_opcode);
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
opcode = g_i386_opcode;
opcode_size = sizeof(g_i386_opcode);
break;
@@ -865,12 +878,6 @@ ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error)
return status;
}
-UnixSignals &
-ProcessPOSIX::GetUnixSignals()
-{
- return m_signals;
-}
-
//------------------------------------------------------------------------------
// Utility functions.
@@ -926,3 +933,16 @@ ProcessPOSIX::IsAThreadRunning()
}
return is_running;
}
+
+const DataBufferSP
+ProcessPOSIX::GetAuxvData ()
+{
+ // If we're the local platform, we can ask the host for auxv data.
+ PlatformSP platform_sp = m_target.GetPlatform ();
+ if (platform_sp && platform_sp->IsHost ())
+ return lldb_private::Host::GetAuxvData(this);
+
+ // Somewhat unexpected - the process is not running locally or we don't have a platform.
+ assert (false && "no platform or not the host - how did we get here with ProcessPOSIX?");
+ return DataBufferSP ();
+}
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.h b/source/Plugins/Process/POSIX/ProcessPOSIX.h
index 7f705d33fe68..033accf17f29 100644
--- a/source/Plugins/Process/POSIX/ProcessPOSIX.h
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.h
@@ -18,7 +18,6 @@
// Other libraries and framework includes
#include "lldb/Target/Process.h"
-#include "lldb/Target/UnixSignals.h"
#include "ProcessMessage.h"
class ProcessMonitor;
@@ -33,7 +32,8 @@ public:
// Constructors and destructors
//------------------------------------------------------------------
ProcessPOSIX(lldb_private::Target& target,
- lldb_private::Listener &listener);
+ lldb_private::Listener &listener,
+ lldb_private::UnixSignalsSP &unix_signals_sp);
virtual
~ProcessPOSIX();
@@ -141,6 +141,9 @@ public:
virtual size_t
PutSTDIN(const char *buf, size_t len, lldb_private::Error &error);
+ const lldb::DataBufferSP
+ GetAuxvData () override;
+
//--------------------------------------------------------------------------
// ProcessPOSIX internal API.
@@ -151,12 +154,7 @@ public:
ProcessMonitor &
GetMonitor() { assert(m_monitor); return *m_monitor; }
- lldb_private::UnixSignals &
- GetUnixSignals();
-
- const char *
- GetFilePath(const lldb_private::ProcessLaunchInfo::FileAction *file_action,
- const char *default_path);
+ const char *GetFilePath(const lldb_private::FileAction *file_action, const char *default_path);
/// Stops all threads in the process.
/// The \p stop_tid parameter indicates the thread which initiated the stop.
@@ -164,7 +162,7 @@ public:
StopAllThreads(lldb::tid_t stop_tid);
/// Adds the thread to the list of threads for which we have received the initial stopping signal.
- /// The \p stop_tid paramter indicates the thread which the stop happened for.
+ /// The \p stop_tid parameter indicates the thread which the stop happened for.
bool
AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
@@ -191,9 +189,6 @@ protected:
/// Drive any exit events to completion.
bool m_exit_now;
- /// OS-specific signal set.
- lldb_private::UnixSignals m_signals;
-
/// Returns true if the process has exited.
bool HasExited();
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp
new file mode 100644
index 000000000000..9109cdb000ae
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp
@@ -0,0 +1,318 @@
+//===-- RegisterContextPOSIXProcessMonitor_arm64.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/Thread.h"
+#include "lldb/Core/RegisterValue.h"
+
+#include "RegisterContextPOSIX_arm64.h"
+#include "ProcessPOSIX.h"
+#include "RegisterContextPOSIXProcessMonitor_arm64.h"
+#include "ProcessMonitor.h"
+
+#define REG_CONTEXT_SIZE (GetGPRSize())
+
+RegisterContextPOSIXProcessMonitor_arm64::RegisterContextPOSIXProcessMonitor_arm64(lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ lldb_private::RegisterInfoInterface *register_info)
+ : RegisterContextPOSIX_arm64(thread, concrete_frame_idx, register_info)
+{
+}
+
+ProcessMonitor &
+RegisterContextPOSIXProcessMonitor_arm64::GetMonitor()
+{
+ lldb::ProcessSP base = CalculateProcess();
+ ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ return process->GetMonitor();
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ReadGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ReadFPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::WriteGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::WriteFPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(const unsigned reg,
+ lldb_private::RegisterValue &value)
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg),
+ GetRegisterName(reg),
+ GetRegisterSize(reg),
+ value);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(const unsigned reg,
+ const lldb_private::RegisterValue &value)
+{
+ unsigned reg_to_write = reg;
+ lldb_private::RegisterValue value_to_write = value;
+
+ // Check if this is a subregister of a full register.
+ const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
+ if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
+ {
+ lldb_private::RegisterValue full_value;
+ uint32_t full_reg = reg_info->invalidate_regs[0];
+ const lldb_private::RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
+
+ // Read the full register.
+ if (ReadRegister(full_reg_info, full_value))
+ {
+ lldb_private::Error error;
+ lldb::ByteOrder byte_order = GetByteOrder();
+ uint8_t dst[lldb_private::RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the full register.
+ const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
+ dst,
+ sizeof(dst),
+ byte_order,
+ error);
+ if (error.Success() && dest_size)
+ {
+ uint8_t src[lldb_private::RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the source data.
+ const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
+ if (error.Success() && src_size && (src_size < dest_size))
+ {
+ // Copy the src bytes to the destination.
+ ::memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
+ // Set this full register as the value to write.
+ value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
+ value_to_write.SetType(full_reg_info);
+ reg_to_write = full_reg;
+ }
+ }
+ }
+ }
+
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg_to_write),
+ GetRegisterName(reg_to_write),
+ value_to_write);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value)
+{
+ if (!reg_info)
+ return false;
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (IsFPR(reg))
+ {
+ if (!ReadFPR())
+ return false;
+ }
+ else
+ {
+ uint32_t full_reg = reg;
+ bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
+
+ if (is_subreg)
+ {
+ // Read the full aligned 64-bit register.
+ full_reg = reg_info->invalidate_regs[0];
+ }
+ return ReadRegister(full_reg, value);
+ }
+
+ // Get pointer to m_fpr variable and set the data from it.
+ assert (reg_info->byte_offset < sizeof m_fpr);
+ uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
+ switch (reg_info->byte_size)
+ {
+ case 2:
+ value.SetUInt16(*(uint16_t *)src);
+ return true;
+ case 4:
+ value.SetUInt32(*(uint32_t *)src);
+ return true;
+ case 8:
+ value.SetUInt64(*(uint64_t *)src);
+ return true;
+ default:
+ assert(false && "Unhandled data size.");
+ return false;
+ }
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value)
+{
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (IsGPR(reg))
+ return WriteRegister(reg, value);
+
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+ bool success = false;
+ data_sp.reset (new lldb_private::DataBufferHeap (REG_CONTEXT_SIZE, 0));
+ if (data_sp && ReadGPR () && ReadFPR ())
+ {
+ uint8_t *dst = data_sp->GetBytes();
+ success = dst != 0;
+
+ if (success)
+ {
+ ::memcpy (dst, &m_gpr_arm64, GetGPRSize());
+ dst += GetGPRSize();
+ ::memcpy (dst, &m_fpr, sizeof m_fpr);
+ }
+ }
+ return success;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+ bool success = false;
+ if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+ {
+ uint8_t *src = data_sp->GetBytes();
+ if (src)
+ {
+ ::memcpy (&m_gpr_arm64, src, GetGPRSize());
+ if (WriteGPR()) {
+ src += GetGPRSize();
+ ::memcpy (&m_fpr, src, sizeof m_fpr);
+ success = WriteFPR();
+ }
+ }
+ }
+ return success;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+ bool read, bool write)
+{
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+ uint32_t hw_index;
+
+ for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
+ {
+ if (IsWatchpointVacant(hw_index))
+ return SetHardwareWatchpointWithIndex(addr, size,
+ read, write,
+ hw_index);
+ }
+
+ return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ClearHardwareWatchpoint(uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::HardwareSingleStep(bool enable)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::UpdateAfterBreakpoint()
+{
+ // PC points one byte past the int3 responsible for the breakpoint.
+ lldb::addr_t pc;
+
+ if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+ return false;
+
+ SetPC(pc - 1);
+ return true;
+}
+
+unsigned
+RegisterContextPOSIXProcessMonitor_arm64::GetRegisterIndexFromOffset(unsigned offset)
+{
+ unsigned reg;
+ for (reg = 0; reg < k_num_registers_arm64; reg++)
+ {
+ if (GetRegisterInfo()[reg].byte_offset == offset)
+ break;
+ }
+ assert(reg < k_num_registers_arm64 && "Invalid register offset.");
+ return reg;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointHit(uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ClearWatchpointHits()
+{
+ return false;
+}
+
+lldb::addr_t
+RegisterContextPOSIXProcessMonitor_arm64::GetWatchpointAddress(uint32_t hw_index)
+{
+ return LLDB_INVALID_ADDRESS;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointVacant(uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
+ bool read, bool write,
+ uint32_t hw_index)
+{
+ return false;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_arm64::NumSupportedHardwareWatchpoints()
+{
+ return 0;
+}
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.h
new file mode 100644
index 000000000000..eb24d4852ab8
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.h
@@ -0,0 +1,95 @@
+//===-- RegisterContextPOSIXProcessMonitor_arm64.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_arm64_H_
+#define liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_
+
+#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
+
+class RegisterContextPOSIXProcessMonitor_arm64:
+ public RegisterContextPOSIX_arm64,
+ public POSIXBreakpointProtocol
+{
+public:
+ RegisterContextPOSIXProcessMonitor_arm64(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_mips64.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp
index f70d00e98a3e..9bfe236de139 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp
@@ -22,7 +22,7 @@ using namespace lldb;
RegisterContextPOSIXProcessMonitor_mips64::RegisterContextPOSIXProcessMonitor_mips64(Thread &thread,
uint32_t concrete_frame_idx,
- RegisterInfoInterface *register_info)
+ lldb_private::RegisterInfoInterface *register_info)
: RegisterContextPOSIX_mips64(thread, concrete_frame_idx, register_info)
{
}
@@ -196,7 +196,6 @@ RegisterContextPOSIXProcessMonitor_mips64::ReadAllRegisterValues(DataBufferSP &d
if (success)
{
::memcpy (dst, &m_gpr_mips64, GetGPRSize());
- dst += GetGPRSize();
}
}
return success;
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h
index 8f545eef0d5e..79e4468b1adf 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
-#include "Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
class RegisterContextPOSIXProcessMonitor_mips64:
public RegisterContextPOSIX_mips64,
@@ -19,7 +19,7 @@ class RegisterContextPOSIXProcessMonitor_mips64:
public:
RegisterContextPOSIXProcessMonitor_mips64(lldb_private::Thread &thread,
uint32_t concrete_frame_idx,
- RegisterInfoInterface *register_info);
+ lldb_private::RegisterInfoInterface *register_info);
protected:
bool
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
index c446bbfa7dce..e534f3b4f9d0 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
@@ -53,7 +53,7 @@ size_and_rw_bits(size_t size, bool read, bool write)
RegisterContextPOSIXProcessMonitor_x86_64::RegisterContextPOSIXProcessMonitor_x86_64(Thread &thread,
uint32_t concrete_frame_idx,
- RegisterInfoInterface *register_info)
+ lldb_private::RegisterInfoInterface *register_info)
: RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info)
{
}
@@ -347,12 +347,12 @@ RegisterContextPOSIXProcessMonitor_x86_64::ReadAllRegisterValues(DataBufferSP &d
if (success)
{
- ::memcpy (dst, &m_gpr_x86_64, GetGPRSize());
- dst += GetGPRSize();
+ ::memcpy (dst, &m_gpr_x86_64, GetGPRSize());
+ dst += GetGPRSize();
+ if (GetFPRType() == eFXSAVE)
+ ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
}
- if (GetFPRType() == eFXSAVE)
- ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
-
+
if (GetFPRType() == eXSAVE)
{
ByteOrder byte_order = GetByteOrder();
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h
index 2b64fa8003a2..2afb195c4c36 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
-#include "Plugins/Process/POSIX/RegisterContextPOSIX_x86.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
class RegisterContextPOSIXProcessMonitor_x86_64:
public RegisterContextPOSIX_x86,
@@ -19,7 +19,7 @@ class RegisterContextPOSIXProcessMonitor_x86_64:
public:
RegisterContextPOSIXProcessMonitor_x86_64(lldb_private::Thread &thread,
uint32_t concrete_frame_idx,
- RegisterInfoInterface *register_info);
+ lldb_private::RegisterInfoInterface *register_info);
protected:
bool
diff --git a/source/Plugins/Process/Utility/ARMDefines.h b/source/Plugins/Process/Utility/ARMDefines.h
index 4b1f06a2f9cd..2c8ad3586af1 100644
--- a/source/Plugins/Process/Utility/ARMDefines.h
+++ b/source/Plugins/Process/Utility/ARMDefines.h
@@ -10,7 +10,7 @@
#ifndef lldb_ARMDefines_h_
#define lldb_ARMDefines_h_
-// Common defintions for the ARM/Thumb Instruction Set Architecture.
+// Common definitions for the ARM/Thumb Instruction Set Architecture.
namespace lldb_private {
diff --git a/source/Plugins/Process/Utility/ARMUtils.h b/source/Plugins/Process/Utility/ARMUtils.h
index 76d64e15a53e..b6ba3fea6928 100644
--- a/source/Plugins/Process/Utility/ARMUtils.h
+++ b/source/Plugins/Process/Utility/ARMUtils.h
@@ -316,7 +316,7 @@ static inline uint32_t ARMExpandImm(uint32_t opcode)
// (imm32, carry_out) = ThumbExpandImm_C(imm12, carry_in)
static inline uint32_t ThumbExpandImm_C(uint32_t opcode, uint32_t carry_in, uint32_t &carry_out)
{
- uint32_t imm32; // the expaned result
+ uint32_t imm32; // the expanded result
const uint32_t i = bit(opcode, 26);
const uint32_t imm3 = bits(opcode, 14, 12);
const uint32_t abcdefgh = bits(opcode, 7, 0);
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index dc90b7ae02c3..3507ccf92065 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -115,7 +115,7 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
RegisterInfo reg_info;
std::vector<uint32_t> value_regs;
std::vector<uint32_t> invalidate_regs;
- bzero (&reg_info, sizeof(reg_info));
+ memset(&reg_info, 0, sizeof(reg_info));
reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString();
if (reg_info.name == NULL)
@@ -323,7 +323,7 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
reg_info.encoding = (Encoding)reg_info_dict.GetItemForKeyAsInteger (encoding_pystr, eEncodingUint);
const int64_t set = reg_info_dict.GetItemForKeyAsInteger(set_pystr, -1);
- if (set >= m_sets.size())
+ if (static_cast<size_t>(set) >= m_sets.size())
{
Clear();
return 0;
@@ -379,7 +379,7 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
if (invalidate_reg_num)
{
const int64_t r = invalidate_reg_num.GetInteger();
- if (r != UINT64_MAX)
+ if (r != static_cast<int64_t>(UINT64_MAX))
m_invalidate_regs_map[i].push_back(r);
else
printf("error: 'invalidate-regs' list value wasn't a valid integer\n");
@@ -632,10 +632,11 @@ DynamicRegisterInfo::Dump () const
{
StreamFile s(stdout, false);
const size_t num_regs = m_regs.size();
- s.Printf("%p: DynamicRegisterInfo contains %zu registers:\n", this, num_regs);
+ s.Printf("%p: DynamicRegisterInfo contains %" PRIu64 " registers:\n",
+ static_cast<const void*>(this), static_cast<uint64_t>(num_regs));
for (size_t i=0; i<num_regs; ++i)
{
- s.Printf("[%3zu] name = %-10s", i, m_regs[i].name);
+ s.Printf("[%3" PRIu64 "] name = %-10s", (uint64_t)i, m_regs[i].name);
s.Printf(", size = %2u, offset = %4u, encoding = %u, format = %-10s",
m_regs[i].byte_size,
m_regs[i].byte_offset,
@@ -671,12 +672,13 @@ DynamicRegisterInfo::Dump () const
}
s.EOL();
}
-
+
const size_t num_sets = m_sets.size();
- s.Printf("%p: DynamicRegisterInfo contains %zu register sets:\n", this, num_sets);
+ s.Printf("%p: DynamicRegisterInfo contains %" PRIu64 " register sets:\n",
+ static_cast<const void*>(this), static_cast<uint64_t>(num_sets));
for (size_t i=0; i<num_sets; ++i)
{
- s.Printf("set[%zu] name = %s, regs = [", i, m_sets[i].name);
+ s.Printf("set[%" PRIu64 "] name = %s, regs = [", (uint64_t)i, m_sets[i].name);
for (size_t idx=0; idx<m_sets[i].num_registers; ++idx)
{
s.Printf("%s ", m_regs[m_sets[i].registers[idx]].name);
diff --git a/source/Plugins/Process/Utility/FreeBSDSignals.cpp b/source/Plugins/Process/Utility/FreeBSDSignals.cpp
new file mode 100644
index 000000000000..b7c52aeb6d13
--- /dev/null
+++ b/source/Plugins/Process/Utility/FreeBSDSignals.cpp
@@ -0,0 +1,31 @@
+//===-- FreeBSDSignals.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 "FreeBSDSignals.h"
+
+FreeBSDSignals::FreeBSDSignals()
+ : UnixSignals()
+{
+ Reset();
+}
+
+void
+FreeBSDSignals::Reset()
+{
+ UnixSignals::Reset();
+
+ // SIGNO NAME SHORT NAME SUPPRESS STOP NOTIFY DESCRIPTION
+ // ====== ============ ========== ======== ====== ====== ===================================================
+ AddSignal (32, "SIGTHR", "THR", false, true , true , "thread interrupt");
+ AddSignal (33, "SIGLIBRT", "LIBRT", false, true , true , "reserved by real-time library");
+}
diff --git a/source/Plugins/Process/Utility/FreeBSDSignals.h b/source/Plugins/Process/Utility/FreeBSDSignals.h
new file mode 100644
index 000000000000..1e14ccb9fc4d
--- /dev/null
+++ b/source/Plugins/Process/Utility/FreeBSDSignals.h
@@ -0,0 +1,28 @@
+//===-- FreeBSDSignals.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_FreeBSDSignals_H_
+#define liblldb_FreeBSDSignals_H_
+
+// Project includes
+#include "lldb/Target/UnixSignals.h"
+
+/// FreeBSD specific set of Unix signals.
+class FreeBSDSignals
+ : public lldb_private::UnixSignals
+{
+public:
+ FreeBSDSignals();
+
+private:
+ void
+ Reset();
+};
+
+#endif // liblldb_FreeBSDSignals_H_
diff --git a/source/Plugins/Process/Utility/HistoryThread.cpp b/source/Plugins/Process/Utility/HistoryThread.cpp
index d045bc7e10d7..590bb0162c8a 100644
--- a/source/Plugins/Process/Utility/HistoryThread.cpp
+++ b/source/Plugins/Process/Utility/HistoryThread.cpp
@@ -20,12 +20,14 @@
using namespace lldb;
using namespace lldb_private;
+// Constructor
+
HistoryThread::HistoryThread (lldb_private::Process &process,
lldb::tid_t tid,
std::vector<lldb::addr_t> pcs,
uint32_t stop_id,
bool stop_id_is_valid) :
- Thread (process, tid),
+ Thread (process, tid, true),
m_framelist_mutex(),
m_framelist(),
m_pcs (pcs),
@@ -40,14 +42,18 @@ HistoryThread::HistoryThread (lldb_private::Process &process,
m_unwinder_ap.reset (new HistoryUnwind (*this, pcs, stop_id, stop_id_is_valid));
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p HistoryThread::HistoryThread", this);
+ log->Printf ("%p HistoryThread::HistoryThread",
+ static_cast<void*>(this));
}
+// Destructor
+
HistoryThread::~HistoryThread ()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p HistoryThread::~HistoryThread (tid=0x%" PRIx64 ")", this, GetID());
+ log->Printf ("%p HistoryThread::~HistoryThread (tid=0x%" PRIx64 ")",
+ static_cast<void*>(this), GetID());
DestroyThread();
}
@@ -72,7 +78,7 @@ HistoryThread::CreateRegisterContextForFrame (StackFrame *frame)
lldb::StackFrameListSP
HistoryThread::GetStackFrameList ()
{
- Mutex::Locker (m_framelist_mutex);
+ Mutex::Locker (m_framelist_mutex); // FIXME do not throw away the lock after we acquire it..
if (m_framelist.get() == NULL)
{
m_framelist.reset (new StackFrameList (*this, StackFrameListSP(), true));
diff --git a/source/Plugins/Process/Utility/HistoryUnwind.cpp b/source/Plugins/Process/Utility/HistoryUnwind.cpp
index 86665fd17b13..f809ebedcfc8 100644
--- a/source/Plugins/Process/Utility/HistoryUnwind.cpp
+++ b/source/Plugins/Process/Utility/HistoryUnwind.cpp
@@ -20,6 +20,8 @@
using namespace lldb;
using namespace lldb_private;
+// Constructor
+
HistoryUnwind::HistoryUnwind (Thread &thread,
std::vector<lldb::addr_t> pcs,
uint32_t stop_id,
@@ -31,6 +33,8 @@ HistoryUnwind::HistoryUnwind (Thread &thread,
{
}
+// Destructor
+
HistoryUnwind::~HistoryUnwind ()
{
}
@@ -62,7 +66,7 @@ HistoryUnwind::DoCreateRegisterContextForFrame (StackFrame *frame)
bool
HistoryUnwind::DoGetFrameInfoAtIndex (uint32_t frame_idx, lldb::addr_t& cfa, lldb::addr_t& pc)
{
- Mutex::Locker (m_unwind_mutex);
+ Mutex::Locker (m_unwind_mutex); // FIXME do not throw away the lock after we acquire it..
if (frame_idx < m_pcs.size())
{
cfa = frame_idx;
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 1d5d19fad25f..4a94457466be 100644
--- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -117,11 +117,11 @@ lldb_private::InferiorCallMmap (Process *process,
{
ExecutionContext exe_ctx;
frame->CalculateExecutionContext (exe_ctx);
- ExecutionResults result = process->RunThreadPlan (exe_ctx,
+ ExpressionResults result = process->RunThreadPlan (exe_ctx,
call_plan_sp,
options,
error_strm);
- if (result == eExecutionCompleted)
+ if (result == eExpressionCompleted)
{
allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
@@ -202,11 +202,11 @@ lldb_private::InferiorCallMunmap (Process *process,
{
ExecutionContext exe_ctx;
frame->CalculateExecutionContext (exe_ctx);
- ExecutionResults result = process->RunThreadPlan (exe_ctx,
+ ExpressionResults result = process->RunThreadPlan (exe_ctx,
call_plan_sp,
options,
error_strm);
- if (result == eExecutionCompleted)
+ if (result == eExpressionCompleted)
{
return true;
}
@@ -260,11 +260,11 @@ lldb_private::InferiorCall (Process *process,
{
ExecutionContext exe_ctx;
frame->CalculateExecutionContext (exe_ctx);
- ExecutionResults result = process->RunThreadPlan (exe_ctx,
+ ExpressionResults result = process->RunThreadPlan (exe_ctx,
call_plan_sp,
options,
error_strm);
- if (result == eExecutionCompleted)
+ if (result == eExpressionCompleted)
{
returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
diff --git a/source/Plugins/Process/Utility/InstructionUtils.h b/source/Plugins/Process/Utility/InstructionUtils.h
index 4bb644e6efe6..813990095c49 100644
--- a/source/Plugins/Process/Utility/InstructionUtils.h
+++ b/source/Plugins/Process/Utility/InstructionUtils.h
@@ -83,6 +83,8 @@ Rotl32 (uint32_t bits, uint32_t amt)
static inline uint64_t
MaskUpToBit (const uint64_t bit)
{
+ if (bit >= 63)
+ return -1ll;
return (1ull << (bit + 1ull)) - 1ull;
}
diff --git a/source/Plugins/Process/Utility/LinuxSignals.cpp b/source/Plugins/Process/Utility/LinuxSignals.cpp
new file mode 100644
index 000000000000..fb49df681cae
--- /dev/null
+++ b/source/Plugins/Process/Utility/LinuxSignals.cpp
@@ -0,0 +1,62 @@
+//===-- LinuxSignals.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
+// Other libraries and framework includes
+// Project includes
+#include "LinuxSignals.h"
+
+using namespace process_linux;
+
+LinuxSignals::LinuxSignals()
+ : UnixSignals()
+{
+ Reset();
+}
+
+void
+LinuxSignals::Reset()
+{
+ m_signals.clear();
+
+ AddSignal (1, "SIGHUP", "HUP", false, true , true , "hangup");
+ AddSignal (2, "SIGINT", "INT", true , true , true , "interrupt");
+ AddSignal (3, "SIGQUIT", "QUIT", false, true , true , "quit");
+ AddSignal (4, "SIGILL", "ILL", false, true , true , "illegal instruction");
+ AddSignal (5, "SIGTRAP", "TRAP", true , true , true , "trace trap (not reset when caught)");
+ AddSignal (6, "SIGABRT", "ABRT", false, true , true , "abort()");
+ AddSignal (6, "SIGIOT", "IOT", false, true , true , "IOT trap");
+ AddSignal (7, "SIGBUS", "BUS", false, true , true , "bus error");
+ AddSignal (8, "SIGFPE", "FPE", false, true , true , "floating point exception");
+ AddSignal (9, "SIGKILL", "KILL", false, true , true , "kill");
+ AddSignal (10, "SIGUSR1", "USR1", false, true , true , "user defined signal 1");
+ AddSignal (11, "SIGSEGV", "SEGV", false, true , true , "segmentation violation");
+ AddSignal (12, "SIGUSR2", "USR2", false, true , true , "user defined signal 2");
+ AddSignal (13, "SIGPIPE", "PIPE", false, true , true , "write to pipe with reading end closed");
+ AddSignal (14, "SIGALRM", "ALRM", false, false, false, "alarm");
+ AddSignal (15, "SIGTERM", "TERM", false, true , true , "termination requested");
+ AddSignal (16, "SIGSTKFLT", "STKFLT", false, true , true , "stack fault");
+ AddSignal (16, "SIGCLD", "CLD", false, false, true , "same as SIGCHLD");
+ AddSignal (17, "SIGCHLD", "CHLD", false, false, true , "child status has changed");
+ AddSignal (18, "SIGCONT", "CONT", false, true , true , "process continue");
+ AddSignal (19, "SIGSTOP", "STOP", true , true , true , "process stop");
+ AddSignal (20, "SIGTSTP", "TSTP", false, true , true , "tty stop");
+ AddSignal (21, "SIGTTIN", "TTIN", false, true , true , "background tty read");
+ AddSignal (22, "SIGTTOU", "TTOU", false, true , true , "background tty write");
+ AddSignal (23, "SIGURG", "URG", false, true , true , "urgent data on socket");
+ 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 (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");
+ AddSignal (30, "SIGPWR", "PWR", false, true , true , "power failure");
+ AddSignal (31, "SIGSYS", "SYS", false, true , true , "invalid system call");
+}
diff --git a/source/Plugins/Process/Utility/LinuxSignals.h b/source/Plugins/Process/Utility/LinuxSignals.h
new file mode 100644
index 000000000000..9645b3d8725a
--- /dev/null
+++ b/source/Plugins/Process/Utility/LinuxSignals.h
@@ -0,0 +1,35 @@
+//===-- LinuxSignals.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_LinuxSignals_H_
+#define liblldb_LinuxSignals_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/UnixSignals.h"
+
+namespace process_linux
+{
+
+ /// Linux specific set of Unix signals.
+ class LinuxSignals
+ : public lldb_private::UnixSignals
+ {
+ public:
+ LinuxSignals();
+
+ private:
+ void
+ Reset();
+ };
+}
+
+#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
index 4d77b6f20fdc..4138a6aaa2aa 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -37,6 +37,8 @@
#include "ARM_GCC_Registers.h"
#include "ARM_DWARF_Registers.h"
+#include "llvm/ADT/STLExtras.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -399,7 +401,7 @@ g_exc_regnums[] =
exc_far,
};
-static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
+static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
void
RegisterContextDarwin_arm::InvalidateAllRegisters ()
@@ -438,9 +440,9 @@ RegisterContextDarwin_arm::GetRegisterInfos ()
// Number of registers in each register set
-const size_t k_num_gpr_registers = sizeof(g_gpr_regnums) / sizeof(uint32_t);
-const size_t k_num_fpu_registers = sizeof(g_fpu_regnums) / sizeof(uint32_t);
-const size_t k_num_exc_registers = sizeof(g_exc_regnums) / sizeof(uint32_t);
+const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
+const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
+const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
//----------------------------------------------------------------------
// Register set definitions. The first definitions at register set index
@@ -454,7 +456,7 @@ static const RegisterSet g_reg_sets[] =
{ "Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums }
};
-const size_t k_num_regsets = sizeof(g_reg_sets) / sizeof(RegisterSet);
+const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
size_t
@@ -473,7 +475,7 @@ RegisterContextDarwin_arm::GetRegisterSet (size_t reg_set)
//----------------------------------------------------------------------
-// Register information defintions for 32 bit i386.
+// Register information definitions for 32 bit i386.
//----------------------------------------------------------------------
int
RegisterContextDarwin_arm::GetSetForNativeRegNum (int reg)
@@ -864,7 +866,7 @@ RegisterContextDarwin_arm::WriteAllRegisterValues (const lldb::DataBufferSP &dat
}
uint32_t
-RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg)
+RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t reg)
{
if (kind == eRegisterKindGeneric)
{
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
index 0bf204f57c80..23134efd43e6 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
@@ -87,7 +87,7 @@ public:
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
virtual uint32_t
NumSupportedHardwareBreakpoints ();
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
new file mode 100644
index 000000000000..e08a87369e4d
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -0,0 +1,944 @@
+//===-- RegisterContextDarwin_arm64.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__)
+
+#include "RegisterContextDarwin_arm64.h"
+
+// C Includes
+#include <mach/mach_types.h>
+#include <mach/thread_act.h>
+#include <sys/sysctl.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Host/Endian.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Compiler.h"
+
+#include "Plugins/Process/Utility/InstructionUtils.h"
+
+// Support building against older versions of LLVM, this macro was added
+// recently.
+#ifndef LLVM_EXTENSION
+#define LLVM_EXTENSION
+#endif
+
+// Project includes
+#include "ARM64_GCC_Registers.h"
+#include "ARM64_DWARF_Registers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(Thread &thread, uint32_t concrete_frame_idx) :
+ RegisterContext(thread, concrete_frame_idx),
+ gpr(),
+ fpu(),
+ exc()
+{
+ uint32_t i;
+ for (i=0; i<kNumErrors; i++)
+ {
+ gpr_errs[i] = -1;
+ fpu_errs[i] = -1;
+ exc_errs[i] = -1;
+ }
+}
+
+RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64()
+{
+}
+
+
+#define GPR_OFFSET(idx) ((idx) * 8)
+#define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::GPR, reg))
+
+#define FPU_OFFSET(idx) ((idx) * 16 + sizeof (RegisterContextDarwin_arm64::GPR))
+#define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::FPU, reg))
+
+#define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::EXC, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU))
+#define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::DBG, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC))
+
+#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextDarwin_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL
+#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC))
+
+//-----------------------------------------------------------------------------
+// Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure.
+//-----------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_ARM64_STRUCT
+#include "RegisterInfos_arm64.h"
+#undef DECLARE_REGISTER_INFOS_ARM64_STRUCT
+
+// General purpose registers
+static uint32_t
+g_gpr_regnums[] =
+{
+ gpr_x0,
+ gpr_x1,
+ gpr_x2,
+ gpr_x3,
+ gpr_x4,
+ gpr_x5,
+ gpr_x6,
+ gpr_x7,
+ gpr_x8,
+ gpr_x9,
+ gpr_x10,
+ gpr_x11,
+ gpr_x12,
+ gpr_x13,
+ gpr_x14,
+ gpr_x15,
+ gpr_x16,
+ gpr_x17,
+ gpr_x18,
+ gpr_x19,
+ gpr_x20,
+ gpr_x21,
+ gpr_x22,
+ gpr_x23,
+ gpr_x24,
+ gpr_x25,
+ gpr_x26,
+ gpr_x27,
+ gpr_x28,
+ gpr_fp,
+ gpr_lr,
+ gpr_sp,
+ gpr_pc,
+ gpr_cpsr
+};
+
+// Floating point registers
+static uint32_t
+g_fpu_regnums[] =
+{
+ fpu_v0,
+ fpu_v1,
+ fpu_v2,
+ fpu_v3,
+ fpu_v4,
+ fpu_v5,
+ fpu_v6,
+ fpu_v7,
+ fpu_v8,
+ fpu_v9,
+ fpu_v10,
+ fpu_v11,
+ fpu_v12,
+ fpu_v13,
+ fpu_v14,
+ fpu_v15,
+ fpu_v16,
+ fpu_v17,
+ fpu_v18,
+ fpu_v19,
+ fpu_v20,
+ fpu_v21,
+ fpu_v22,
+ fpu_v23,
+ fpu_v24,
+ fpu_v25,
+ fpu_v26,
+ fpu_v27,
+ fpu_v28,
+ fpu_v29,
+ fpu_v30,
+ fpu_v31,
+ fpu_fpsr,
+ fpu_fpcr
+};
+
+// Exception registers
+
+static uint32_t
+g_exc_regnums[] =
+{
+ exc_far,
+ exc_esr,
+ exc_exception
+};
+
+static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos_arm64);
+
+void
+RegisterContextDarwin_arm64::InvalidateAllRegisters ()
+{
+ InvalidateAllRegisterStates();
+}
+
+
+size_t
+RegisterContextDarwin_arm64::GetRegisterCount ()
+{
+ assert(k_num_register_infos == k_num_registers);
+ return k_num_registers;
+}
+
+const RegisterInfo *
+RegisterContextDarwin_arm64::GetRegisterInfoAtIndex (size_t reg)
+{
+ assert(k_num_register_infos == k_num_registers);
+ if (reg < k_num_registers)
+ return &g_register_infos_arm64[reg];
+ return NULL;
+}
+
+size_t
+RegisterContextDarwin_arm64::GetRegisterInfosCount ()
+{
+ return k_num_register_infos;
+}
+
+const RegisterInfo *
+RegisterContextDarwin_arm64::GetRegisterInfos ()
+{
+ return g_register_infos_arm64;
+}
+
+
+// Number of registers in each register set
+const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
+const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
+const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
+
+//----------------------------------------------------------------------
+// Register set definitions. The first definitions at register set index
+// of zero is for all registers, followed by other registers sets. The
+// register information for the all register set need not be filled in.
+//----------------------------------------------------------------------
+static const RegisterSet g_reg_sets[] =
+{
+ { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums, },
+ { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums },
+ { "Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums }
+};
+
+const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
+
+
+size_t
+RegisterContextDarwin_arm64::GetRegisterSetCount ()
+{
+ return k_num_regsets;
+}
+
+const RegisterSet *
+RegisterContextDarwin_arm64::GetRegisterSet (size_t reg_set)
+{
+ if (reg_set < k_num_regsets)
+ return &g_reg_sets[reg_set];
+ return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// Register information definitions for arm64
+//----------------------------------------------------------------------
+int
+RegisterContextDarwin_arm64::GetSetForNativeRegNum (int reg)
+{
+ if (reg < fpu_v0)
+ return GPRRegSet;
+ else if (reg < exc_far)
+ return FPURegSet;
+ else if (reg < k_num_registers)
+ return EXCRegSet;
+ return -1;
+}
+
+int
+RegisterContextDarwin_arm64::ReadGPR (bool force)
+{
+ int set = GPRRegSet;
+ if (force || !RegisterSetIsCached(set))
+ {
+ SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
+ }
+ return GetError(GPRRegSet, Read);
+}
+
+int
+RegisterContextDarwin_arm64::ReadFPU (bool force)
+{
+ int set = FPURegSet;
+ if (force || !RegisterSetIsCached(set))
+ {
+ SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
+ }
+ return GetError(FPURegSet, Read);
+}
+
+int
+RegisterContextDarwin_arm64::ReadEXC (bool force)
+{
+ int set = EXCRegSet;
+ if (force || !RegisterSetIsCached(set))
+ {
+ SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
+ }
+ return GetError(EXCRegSet, Read);
+}
+
+int
+RegisterContextDarwin_arm64::ReadDBG (bool force)
+{
+ int set = DBGRegSet;
+ if (force || !RegisterSetIsCached(set))
+ {
+ SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));
+ }
+ return GetError(DBGRegSet, Read);
+}
+
+int
+RegisterContextDarwin_arm64::WriteGPR ()
+{
+ int set = GPRRegSet;
+ if (!RegisterSetIsCached(set))
+ {
+ SetError (set, Write, -1);
+ return KERN_INVALID_ARGUMENT;
+ }
+ SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr));
+ SetError (set, Read, -1);
+ return GetError(GPRRegSet, Write);
+}
+
+int
+RegisterContextDarwin_arm64::WriteFPU ()
+{
+ int set = FPURegSet;
+ if (!RegisterSetIsCached(set))
+ {
+ SetError (set, Write, -1);
+ return KERN_INVALID_ARGUMENT;
+ }
+ SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu));
+ SetError (set, Read, -1);
+ return GetError(FPURegSet, Write);
+}
+
+int
+RegisterContextDarwin_arm64::WriteEXC ()
+{
+ int set = EXCRegSet;
+ if (!RegisterSetIsCached(set))
+ {
+ SetError (set, Write, -1);
+ return KERN_INVALID_ARGUMENT;
+ }
+ SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc));
+ SetError (set, Read, -1);
+ return GetError(EXCRegSet, Write);
+}
+
+int
+RegisterContextDarwin_arm64::WriteDBG ()
+{
+ int set = DBGRegSet;
+ if (!RegisterSetIsCached(set))
+ {
+ SetError (set, Write, -1);
+ return KERN_INVALID_ARGUMENT;
+ }
+ SetError (set, Write, DoWriteDBG(GetThreadID(), set, dbg));
+ SetError (set, Read, -1);
+ return GetError(DBGRegSet, Write);
+}
+
+
+int
+RegisterContextDarwin_arm64::ReadRegisterSet (uint32_t set, bool force)
+{
+ switch (set)
+ {
+ case GPRRegSet: return ReadGPR(force);
+ case FPURegSet: return ReadFPU(force);
+ case EXCRegSet: return ReadEXC(force);
+ case DBGRegSet: return ReadDBG(force);
+ default: break;
+ }
+ return KERN_INVALID_ARGUMENT;
+}
+
+int
+RegisterContextDarwin_arm64::WriteRegisterSet (uint32_t set)
+{
+ // Make sure we have a valid context to set.
+ if (RegisterSetIsCached(set))
+ {
+ switch (set)
+ {
+ case GPRRegSet: return WriteGPR();
+ case FPURegSet: return WriteFPU();
+ case EXCRegSet: return WriteEXC();
+ case DBGRegSet: return WriteDBG();
+ default: break;
+ }
+ }
+ return KERN_INVALID_ARGUMENT;
+}
+
+void
+RegisterContextDarwin_arm64::LogDBGRegisters (Log *log, const DBG& dbg)
+{
+ if (log)
+ {
+ for (uint32_t i=0; i<16; i++)
+ log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8llx, 0x%8.8llx } WVR%-2u/WCR%-2u = { 0x%8.8llx, 0x%8.8llx }",
+ i, i, dbg.bvr[i], dbg.bcr[i],
+ i, i, dbg.wvr[i], dbg.wcr[i]);
+ }
+}
+
+
+bool
+RegisterContextDarwin_arm64::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
+{
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ int set = RegisterContextDarwin_arm64::GetSetForNativeRegNum (reg);
+
+ if (set == -1)
+ return false;
+
+ if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+ return false;
+
+ switch (reg)
+ {
+ case gpr_x0:
+ case gpr_x1:
+ case gpr_x2:
+ case gpr_x3:
+ case gpr_x4:
+ case gpr_x5:
+ case gpr_x6:
+ case gpr_x7:
+ case gpr_x8:
+ case gpr_x9:
+ case gpr_x10:
+ case gpr_x11:
+ case gpr_x12:
+ case gpr_x13:
+ case gpr_x14:
+ case gpr_x15:
+ case gpr_x16:
+ case gpr_x17:
+ case gpr_x18:
+ case gpr_x19:
+ case gpr_x20:
+ case gpr_x21:
+ case gpr_x22:
+ case gpr_x23:
+ case gpr_x24:
+ case gpr_x25:
+ case gpr_x26:
+ case gpr_x27:
+ case gpr_x28:
+ case gpr_fp:
+ case gpr_sp:
+ case gpr_lr:
+ case gpr_pc:
+ case gpr_cpsr:
+ value.SetUInt64 (gpr.x[reg - gpr_x0]);
+ break;
+
+ case fpu_v0:
+ case fpu_v1:
+ case fpu_v2:
+ case fpu_v3:
+ case fpu_v4:
+ case fpu_v5:
+ case fpu_v6:
+ case fpu_v7:
+ case fpu_v8:
+ case fpu_v9:
+ case fpu_v10:
+ case fpu_v11:
+ case fpu_v12:
+ case fpu_v13:
+ case fpu_v14:
+ case fpu_v15:
+ case fpu_v16:
+ case fpu_v17:
+ case fpu_v18:
+ case fpu_v19:
+ case fpu_v20:
+ case fpu_v21:
+ case fpu_v22:
+ case fpu_v23:
+ case fpu_v24:
+ case fpu_v25:
+ case fpu_v26:
+ case fpu_v27:
+ case fpu_v28:
+ case fpu_v29:
+ case fpu_v30:
+ case fpu_v31:
+ value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder());
+ break;
+
+ case fpu_fpsr:
+ value.SetUInt32 (fpu.fpsr);
+ break;
+
+ case fpu_fpcr:
+ value.SetUInt32 (fpu.fpcr);
+ break;
+
+ case exc_exception:
+ value.SetUInt32 (exc.exception);
+ break;
+ case exc_esr:
+ value.SetUInt32 (exc.esr);
+ break;
+ case exc_far:
+ value.SetUInt64 (exc.far);
+ break;
+
+ default:
+ value.SetValueToInvalid();
+ return false;
+
+ }
+ return true;
+}
+
+
+bool
+RegisterContextDarwin_arm64::WriteRegister (const RegisterInfo *reg_info,
+ const RegisterValue &value)
+{
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ int set = GetSetForNativeRegNum (reg);
+
+ if (set == -1)
+ return false;
+
+ if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+ return false;
+
+ switch (reg)
+ {
+ case gpr_x0:
+ case gpr_x1:
+ case gpr_x2:
+ case gpr_x3:
+ case gpr_x4:
+ case gpr_x5:
+ case gpr_x6:
+ case gpr_x7:
+ case gpr_x8:
+ case gpr_x9:
+ case gpr_x10:
+ case gpr_x11:
+ case gpr_x12:
+ case gpr_x13:
+ case gpr_x14:
+ case gpr_x15:
+ case gpr_x16:
+ case gpr_x17:
+ case gpr_x18:
+ case gpr_x19:
+ case gpr_x20:
+ case gpr_x21:
+ case gpr_x22:
+ case gpr_x23:
+ case gpr_x24:
+ case gpr_x25:
+ case gpr_x26:
+ case gpr_x27:
+ case gpr_x28:
+ case gpr_fp:
+ case gpr_sp:
+ case gpr_lr:
+ case gpr_pc:
+ case gpr_cpsr:
+ gpr.x[reg - gpr_x0] = value.GetAsUInt64();
+ break;
+
+ case fpu_v0:
+ case fpu_v1:
+ case fpu_v2:
+ case fpu_v3:
+ case fpu_v4:
+ case fpu_v5:
+ case fpu_v6:
+ case fpu_v7:
+ case fpu_v8:
+ case fpu_v9:
+ case fpu_v10:
+ case fpu_v11:
+ case fpu_v12:
+ case fpu_v13:
+ case fpu_v14:
+ case fpu_v15:
+ case fpu_v16:
+ case fpu_v17:
+ case fpu_v18:
+ case fpu_v19:
+ case fpu_v20:
+ case fpu_v21:
+ case fpu_v22:
+ case fpu_v23:
+ case fpu_v24:
+ case fpu_v25:
+ case fpu_v26:
+ case fpu_v27:
+ case fpu_v28:
+ case fpu_v29:
+ case fpu_v30:
+ case fpu_v31:
+ ::memcpy (fpu.v[reg].bytes, value.GetBytes(), value.GetByteSize());
+ break;
+
+ case fpu_fpsr:
+ fpu.fpsr = value.GetAsUInt32();
+ break;
+
+ case fpu_fpcr:
+ fpu.fpcr = value.GetAsUInt32();
+ break;
+
+ case exc_exception:
+ exc.exception = value.GetAsUInt32();
+ break;
+ case exc_esr:
+ exc.esr = value.GetAsUInt32();
+ break;
+ case exc_far:
+ exc.far = value.GetAsUInt64();
+ break;
+
+ default:
+ return false;
+
+ }
+ return WriteRegisterSet(set) == KERN_SUCCESS;
+}
+
+bool
+RegisterContextDarwin_arm64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+ data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+ if (data_sp &&
+ ReadGPR (false) == KERN_SUCCESS &&
+ ReadFPU (false) == KERN_SUCCESS &&
+ ReadEXC (false) == KERN_SUCCESS)
+ {
+ uint8_t *dst = data_sp->GetBytes();
+ ::memcpy (dst, &gpr, sizeof(gpr));
+ dst += sizeof(gpr);
+
+ ::memcpy (dst, &fpu, sizeof(fpu));
+ dst += sizeof(gpr);
+
+ ::memcpy (dst, &exc, sizeof(exc));
+ return true;
+ }
+ return false;
+}
+
+bool
+RegisterContextDarwin_arm64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+ if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+ {
+ const uint8_t *src = data_sp->GetBytes();
+ ::memcpy (&gpr, src, sizeof(gpr));
+ src += sizeof(gpr);
+
+ ::memcpy (&fpu, src, sizeof(fpu));
+ src += sizeof(gpr);
+
+ ::memcpy (&exc, src, sizeof(exc));
+ uint32_t success_count = 0;
+ if (WriteGPR() == KERN_SUCCESS)
+ ++success_count;
+ if (WriteFPU() == KERN_SUCCESS)
+ ++success_count;
+ if (WriteEXC() == KERN_SUCCESS)
+ ++success_count;
+ return success_count == 3;
+ }
+ return false;
+}
+
+uint32_t
+RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber (RegisterKind kind, uint32_t reg)
+{
+ if (kind == eRegisterKindGeneric)
+ {
+ switch (reg)
+ {
+ case LLDB_REGNUM_GENERIC_PC: return gpr_pc;
+ case LLDB_REGNUM_GENERIC_SP: return gpr_sp;
+ case LLDB_REGNUM_GENERIC_FP: return gpr_fp;
+ case LLDB_REGNUM_GENERIC_RA: return gpr_lr;
+ case LLDB_REGNUM_GENERIC_FLAGS: return gpr_cpsr;
+ default:
+ break;
+ }
+ }
+ else if (kind == eRegisterKindDWARF)
+ {
+ switch (reg)
+ {
+ case arm64_dwarf::x0: return gpr_x0;
+ case arm64_dwarf::x1: return gpr_x1;
+ case arm64_dwarf::x2: return gpr_x2;
+ case arm64_dwarf::x3: return gpr_x3;
+ case arm64_dwarf::x4: return gpr_x4;
+ case arm64_dwarf::x5: return gpr_x5;
+ case arm64_dwarf::x6: return gpr_x6;
+ case arm64_dwarf::x7: return gpr_x7;
+ case arm64_dwarf::x8: return gpr_x8;
+ case arm64_dwarf::x9: return gpr_x9;
+ case arm64_dwarf::x10: return gpr_x10;
+ case arm64_dwarf::x11: return gpr_x11;
+ case arm64_dwarf::x12: return gpr_x12;
+ case arm64_dwarf::x13: return gpr_x13;
+ case arm64_dwarf::x14: return gpr_x14;
+ case arm64_dwarf::x15: return gpr_x15;
+ case arm64_dwarf::x16: return gpr_x16;
+ case arm64_dwarf::x17: return gpr_x17;
+ case arm64_dwarf::x18: return gpr_x18;
+ case arm64_dwarf::x19: return gpr_x19;
+ case arm64_dwarf::x20: return gpr_x20;
+ case arm64_dwarf::x21: return gpr_x21;
+ case arm64_dwarf::x22: return gpr_x22;
+ case arm64_dwarf::x23: return gpr_x23;
+ case arm64_dwarf::x24: return gpr_x24;
+ case arm64_dwarf::x25: return gpr_x25;
+ case arm64_dwarf::x26: return gpr_x26;
+ case arm64_dwarf::x27: return gpr_x27;
+ case arm64_dwarf::x28: return gpr_x28;
+
+ case arm64_dwarf::fp: return gpr_fp;
+ case arm64_dwarf::sp: return gpr_sp;
+ case arm64_dwarf::lr: return gpr_lr;
+ case arm64_dwarf::pc: return gpr_pc;
+ case arm64_dwarf::cpsr: return gpr_cpsr;
+
+ case arm64_dwarf::v0: return fpu_v0;
+ case arm64_dwarf::v1: return fpu_v1;
+ case arm64_dwarf::v2: return fpu_v2;
+ case arm64_dwarf::v3: return fpu_v3;
+ case arm64_dwarf::v4: return fpu_v4;
+ case arm64_dwarf::v5: return fpu_v5;
+ case arm64_dwarf::v6: return fpu_v6;
+ case arm64_dwarf::v7: return fpu_v7;
+ case arm64_dwarf::v8: return fpu_v8;
+ case arm64_dwarf::v9: return fpu_v9;
+ case arm64_dwarf::v10: return fpu_v10;
+ case arm64_dwarf::v11: return fpu_v11;
+ case arm64_dwarf::v12: return fpu_v12;
+ case arm64_dwarf::v13: return fpu_v13;
+ case arm64_dwarf::v14: return fpu_v14;
+ case arm64_dwarf::v15: return fpu_v15;
+ case arm64_dwarf::v16: return fpu_v16;
+ case arm64_dwarf::v17: return fpu_v17;
+ case arm64_dwarf::v18: return fpu_v18;
+ case arm64_dwarf::v19: return fpu_v19;
+ case arm64_dwarf::v20: return fpu_v20;
+ case arm64_dwarf::v21: return fpu_v21;
+ case arm64_dwarf::v22: return fpu_v22;
+ case arm64_dwarf::v23: return fpu_v23;
+ case arm64_dwarf::v24: return fpu_v24;
+ case arm64_dwarf::v25: return fpu_v25;
+ case arm64_dwarf::v26: return fpu_v26;
+ case arm64_dwarf::v27: return fpu_v27;
+ case arm64_dwarf::v28: return fpu_v28;
+ case arm64_dwarf::v29: return fpu_v29;
+ case arm64_dwarf::v30: return fpu_v30;
+ case arm64_dwarf::v31: return fpu_v31;
+
+ default:
+ break;
+ }
+ }
+ else if (kind == eRegisterKindGCC)
+ {
+ switch (reg)
+ {
+ case arm64_gcc::x0: return gpr_x0;
+ case arm64_gcc::x1: return gpr_x1;
+ case arm64_gcc::x2: return gpr_x2;
+ case arm64_gcc::x3: return gpr_x3;
+ case arm64_gcc::x4: return gpr_x4;
+ case arm64_gcc::x5: return gpr_x5;
+ case arm64_gcc::x6: return gpr_x6;
+ case arm64_gcc::x7: return gpr_x7;
+ case arm64_gcc::x8: return gpr_x8;
+ case arm64_gcc::x9: return gpr_x9;
+ case arm64_gcc::x10: return gpr_x10;
+ case arm64_gcc::x11: return gpr_x11;
+ case arm64_gcc::x12: return gpr_x12;
+ case arm64_gcc::x13: return gpr_x13;
+ case arm64_gcc::x14: return gpr_x14;
+ case arm64_gcc::x15: return gpr_x15;
+ case arm64_gcc::x16: return gpr_x16;
+ case arm64_gcc::x17: return gpr_x17;
+ case arm64_gcc::x18: return gpr_x18;
+ case arm64_gcc::x19: return gpr_x19;
+ case arm64_gcc::x20: return gpr_x20;
+ case arm64_gcc::x21: return gpr_x21;
+ case arm64_gcc::x22: return gpr_x22;
+ case arm64_gcc::x23: return gpr_x23;
+ case arm64_gcc::x24: return gpr_x24;
+ case arm64_gcc::x25: return gpr_x25;
+ case arm64_gcc::x26: return gpr_x26;
+ case arm64_gcc::x27: return gpr_x27;
+ case arm64_gcc::x28: return gpr_x28;
+ case arm64_gcc::fp: return gpr_fp;
+ case arm64_gcc::sp: return gpr_sp;
+ case arm64_gcc::lr: return gpr_lr;
+ case arm64_gcc::pc: return gpr_pc;
+ case arm64_gcc::cpsr: return gpr_cpsr;
+ }
+ }
+ else if (kind == eRegisterKindLLDB)
+ {
+ return reg;
+ }
+ return LLDB_INVALID_REGNUM;
+}
+
+
+uint32_t
+RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints ()
+{
+#if defined (__arm64__) || defined (__aarch64__)
+ // autodetect how many watchpoints are supported dynamically...
+ static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
+ if (g_num_supported_hw_watchpoints == UINT32_MAX)
+ {
+ size_t len;
+ uint32_t n = 0;
+ len = sizeof (n);
+ if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0)
+ {
+ g_num_supported_hw_watchpoints = n;
+ }
+ }
+ return g_num_supported_hw_watchpoints;
+#else
+ // TODO: figure out remote case here!
+ return 2;
+#endif
+}
+
+
+uint32_t
+RegisterContextDarwin_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write)
+{
+// if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write);
+
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+
+ // Can't watch zero bytes
+ if (size == 0)
+ return LLDB_INVALID_INDEX32;
+
+ // We must watch for either read or write
+ if (read == false && write == false)
+ return LLDB_INVALID_INDEX32;
+
+ // Can't watch more than 4 bytes per WVR/WCR pair
+ if (size > 4)
+ return LLDB_INVALID_INDEX32;
+
+ // We can only watch up to four bytes that follow a 4 byte aligned address
+ // per watchpoint register pair. Since we have at most so we can only watch
+ // until the next 4 byte boundary and we need to make sure we can properly
+ // encode this.
+ uint32_t addr_word_offset = addr % 4;
+// if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset);
+
+ uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
+// if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask);
+ if (byte_mask > 0xfu)
+ return LLDB_INVALID_INDEX32;
+
+ // Read the debug state
+ int kret = ReadDBG (false);
+
+ if (kret == KERN_SUCCESS)
+ {
+ // Check to make sure we have the needed hardware support
+ uint32_t i = 0;
+
+ for (i=0; i<num_hw_watchpoints; ++i)
+ {
+ if ((dbg.wcr[i] & WCR_ENABLE) == 0)
+ break; // We found an available hw breakpoint slot (in i)
+ }
+
+ // See if we found an available hw breakpoint slot above
+ if (i < num_hw_watchpoints)
+ {
+ // Make the byte_mask into a valid Byte Address Select mask
+ uint32_t byte_address_select = byte_mask << 5;
+ // Make sure bits 1:0 are clear in our address
+ dbg.wvr[i] = addr & ~((lldb::addr_t)3);
+ dbg.wcr[i] = byte_address_select | // Which bytes that follow the IMVA that we will watch
+ S_USER | // Stop only in user mode
+ (read ? WCR_LOAD : 0) | // Stop on read access?
+ (write ? WCR_STORE : 0) | // Stop on write access?
+ WCR_ENABLE; // Enable this watchpoint;
+
+ kret = WriteDBG();
+// if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() WriteDBG() => 0x%8.8x.", kret);
+
+ if (kret == KERN_SUCCESS)
+ return i;
+ }
+ else
+ {
+// if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
+ }
+ }
+ return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContextDarwin_arm64::ClearHardwareWatchpoint (uint32_t hw_index)
+{
+ int kret = ReadDBG (false);
+
+ const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
+ if (kret == KERN_SUCCESS)
+ {
+ if (hw_index < num_hw_points)
+ {
+ dbg.wcr[hw_index] = 0;
+// if (log) log->Printf ("RegisterContextDarwin_arm64::ClearHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x WCR%u = 0x%8.8x",
+// hw_index,
+// hw_index,
+// dbg.wvr[hw_index],
+// hw_index,
+// dbg.wcr[hw_index]);
+
+ kret = WriteDBG();
+
+ if (kret == KERN_SUCCESS)
+ return true;
+ }
+ }
+ return false;
+}
+
+#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
new file mode 100644
index 000000000000..aeac15e9b09a
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
@@ -0,0 +1,296 @@
+//===-- RegisterContextDarwin_arm64.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_RegisterContextDarwin_arm64_h_
+#define liblldb_RegisterContextDarwin_arm64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+
+// Break only in privileged or user mode
+#define S_RSVD ((uint32_t)(0u << 1))
+#define S_PRIV ((uint32_t)(1u << 1))
+#define S_USER ((uint32_t)(2u << 1))
+#define S_PRIV_USER ((S_PRIV) | (S_USER))
+
+#define WCR_ENABLE ((uint32_t)(1u))
+
+// Watchpoint load/store
+#define WCR_LOAD ((uint32_t)(1u << 3))
+#define WCR_STORE ((uint32_t)(1u << 4))
+
+class RegisterContextDarwin_arm64 : public lldb_private::RegisterContext
+{
+public:
+
+ RegisterContextDarwin_arm64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+
+ virtual
+ ~RegisterContextDarwin_arm64();
+
+ virtual void
+ InvalidateAllRegisters ();
+
+ virtual size_t
+ GetRegisterCount ();
+
+ virtual const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex (size_t reg);
+
+ virtual size_t
+ GetRegisterSetCount ();
+
+ virtual const lldb_private::RegisterSet *
+ GetRegisterSet (size_t set);
+
+ virtual bool
+ ReadRegister (const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &reg_value);
+
+ virtual bool
+ WriteRegister (const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &reg_value);
+
+ virtual bool
+ ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+ virtual bool
+ WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+ virtual uint32_t
+ ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+
+ virtual uint32_t
+ NumSupportedHardwareWatchpoints ();
+
+ virtual uint32_t
+ SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
+
+ virtual bool
+ ClearHardwareWatchpoint (uint32_t hw_index);
+
+ // mirrors <mach/arm/thread_status.h> arm_thread_state64_t
+ struct GPR
+ {
+ uint64_t x[29]; // x0-x28
+ uint64_t fp; // x29
+ uint64_t lr; // x30
+ uint64_t sp; // x31
+ uint64_t pc; // pc
+ uint32_t cpsr; // cpsr
+ };
+
+
+ struct VReg
+ {
+ uint8_t bytes[16];
+ };
+
+ // mirrors <mach/arm/thread_status.h> arm_neon_state64_t
+ struct FPU
+ {
+ VReg v[32];
+ uint32_t fpsr;
+ uint32_t fpcr;
+ };
+
+ // mirrors <mach/arm/thread_status.h> arm_exception_state64_t
+ struct EXC
+ {
+ uint64_t far; // Virtual Fault Address
+ uint32_t esr; // Exception syndrome
+ uint32_t exception; // number of arm exception token
+ };
+
+ // mirrors <mach/arm/thread_status.h> arm_debug_state64_t
+ struct DBG
+ {
+ uint64_t bvr[16];
+ uint64_t bcr[16];
+ uint64_t wvr[16];
+ uint64_t wcr[16];
+ uint64_t mdscr_el1;
+ };
+
+ static void
+ LogDBGRegisters (lldb_private::Log *log, const DBG& dbg);
+
+protected:
+
+ enum
+ {
+ GPRRegSet = 6, // ARM_THREAD_STATE64
+ FPURegSet = 17, // ARM_NEON_STATE64
+ EXCRegSet = 7, // ARM_EXCEPTION_STATE64
+ DBGRegSet = 15 // ARM_DEBUG_STATE64
+ };
+
+ enum
+ {
+ GPRWordCount = sizeof(GPR)/sizeof(uint32_t), // ARM_THREAD_STATE64_COUNT
+ FPUWordCount = sizeof(FPU)/sizeof(uint32_t), // ARM_NEON_STATE64_COUNT
+ EXCWordCount = sizeof(EXC)/sizeof(uint32_t), // ARM_EXCEPTION_STATE64_COUNT
+ DBGWordCount = sizeof(DBG)/sizeof(uint32_t) // ARM_DEBUG_STATE64_COUNT
+ };
+
+ enum
+ {
+ Read = 0,
+ Write = 1,
+ kNumErrors = 2
+ };
+
+ GPR gpr;
+ FPU fpu;
+ EXC exc;
+ DBG dbg;
+ int gpr_errs[2]; // Read/Write errors
+ int fpu_errs[2]; // Read/Write errors
+ int exc_errs[2]; // Read/Write errors
+ int dbg_errs[2]; // Read/Write errors
+
+ void
+ InvalidateAllRegisterStates()
+ {
+ SetError (GPRRegSet, Read, -1);
+ SetError (FPURegSet, Read, -1);
+ SetError (EXCRegSet, Read, -1);
+ }
+
+ int
+ GetError (int flavor, uint32_t err_idx) const
+ {
+ if (err_idx < kNumErrors)
+ {
+ switch (flavor)
+ {
+ // When getting all errors, just OR all values together to see if
+ // we got any kind of error.
+ case GPRRegSet: return gpr_errs[err_idx];
+ case FPURegSet: return fpu_errs[err_idx];
+ case EXCRegSet: return exc_errs[err_idx];
+ case DBGRegSet: return dbg_errs[err_idx];
+ default: break;
+ }
+ }
+ return -1;
+ }
+
+ bool
+ SetError (int flavor, uint32_t err_idx, int err)
+ {
+ if (err_idx < kNumErrors)
+ {
+ switch (flavor)
+ {
+ case GPRRegSet:
+ gpr_errs[err_idx] = err;
+ return true;
+
+ case FPURegSet:
+ fpu_errs[err_idx] = err;
+ return true;
+
+ case EXCRegSet:
+ exc_errs[err_idx] = err;
+ return true;
+
+ case DBGRegSet:
+ exc_errs[err_idx] = err;
+ return true;
+
+ default: break;
+ }
+ }
+ return false;
+ }
+
+ bool
+ RegisterSetIsCached (int set) const
+ {
+ return GetError(set, Read) == 0;
+ }
+
+ int
+ ReadGPR (bool force);
+
+ int
+ ReadFPU (bool force);
+
+ int
+ ReadEXC (bool force);
+
+ int
+ ReadDBG (bool force);
+
+ int
+ WriteGPR ();
+
+ int
+ WriteFPU ();
+
+ int
+ WriteEXC ();
+
+ int
+ WriteDBG ();
+
+
+ // Subclasses override these to do the actual reading.
+ virtual int
+ DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
+ {
+ return -1;
+ }
+
+ virtual int
+ DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0;
+
+ virtual int
+ DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0;
+
+ virtual int
+ DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg) = 0;
+
+ virtual int
+ DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
+
+ virtual int
+ DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
+
+ virtual int
+ DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0;
+
+ virtual int
+ DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg) = 0;
+
+ int
+ ReadRegisterSet (uint32_t set, bool force);
+
+ int
+ WriteRegisterSet (uint32_t set);
+
+ static uint32_t
+ GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
+
+ static int
+ GetSetForNativeRegNum (int reg_num);
+
+ static size_t
+ GetRegisterInfosCount ();
+
+ static const lldb_private::RegisterInfo *
+ GetRegisterInfos ();
+};
+
+#endif // liblldb_RegisterContextDarwin_arm64_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
index a94d1f538a28..08144bf7ec26 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -19,6 +19,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Host/Endian.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
// Support building against older versions of LLVM, this macro was added
@@ -281,7 +282,7 @@ static RegisterInfo g_register_infos[] =
{ DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_faultvaddr }, NULL, NULL}
};
-static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
+static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
void
RegisterContextDarwin_i386::InvalidateAllRegisters ()
@@ -384,9 +385,9 @@ g_exc_regnums[] =
};
// Number of registers in each register set
-const size_t k_num_gpr_registers = sizeof(g_gpr_regnums) / sizeof(uint32_t);
-const size_t k_num_fpu_registers = sizeof(g_fpu_regnums) / sizeof(uint32_t);
-const size_t k_num_exc_registers = sizeof(g_exc_regnums) / sizeof(uint32_t);
+const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
+const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
+const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
//----------------------------------------------------------------------
// Register set definitions. The first definitions at register set index
@@ -400,7 +401,7 @@ static const RegisterSet g_reg_sets[] =
{ "Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums }
};
-const size_t k_num_regsets = sizeof(g_reg_sets) / sizeof(RegisterSet);
+const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
size_t
@@ -843,7 +844,7 @@ RegisterContextDarwin_i386::WriteAllRegisterValues (const lldb::DataBufferSP &da
uint32_t
-RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg)
+RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t reg)
{
if (kind == eRegisterKindGeneric)
{
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
index a588494f9dcf..1d03feb9f3dd 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
@@ -55,7 +55,7 @@ public:
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
virtual bool
HardwareSingleStep (bool enable);
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
index 433782fe20c0..54124d187d54 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -9,6 +9,7 @@
// C Includes
+#include <inttypes.h> // PRIx64
#include <stdarg.h>
#include <stddef.h> // offsetof
@@ -20,6 +21,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Host/Endian.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
// Support building against older versions of LLVM, this macro was added
@@ -317,7 +319,7 @@ static RegisterInfo g_register_infos[] =
{ DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_faultvaddr }, NULL, NULL}
};
-static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
+static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
void
@@ -431,9 +433,9 @@ g_exc_regnums[] =
};
// Number of registers in each register set
-const size_t k_num_gpr_registers = sizeof(g_gpr_regnums) / sizeof(uint32_t);
-const size_t k_num_fpu_registers = sizeof(g_fpu_regnums) / sizeof(uint32_t);
-const size_t k_num_exc_registers = sizeof(g_exc_regnums) / sizeof(uint32_t);
+const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
+const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
+const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
//----------------------------------------------------------------------
// Register set definitions. The first definitions at register set index
@@ -447,7 +449,7 @@ static const RegisterSet g_reg_sets[] =
{ "Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums }
};
-const size_t k_num_regsets = sizeof(g_reg_sets) / sizeof(RegisterSet);
+const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
size_t
@@ -902,7 +904,7 @@ RegisterContextDarwin_x86_64::WriteAllRegisterValues (const lldb::DataBufferSP &
uint32_t
-RegisterContextDarwin_x86_64::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg)
+RegisterContextDarwin_x86_64::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t reg)
{
if (kind == eRegisterKindGeneric)
{
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
index 4b8127af997c..09e35e9c423e 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
@@ -54,7 +54,7 @@ public:
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
virtual bool
HardwareSingleStep (bool enable);
diff --git a/source/Plugins/Process/Utility/RegisterContextDummy.cpp b/source/Plugins/Process/Utility/RegisterContextDummy.cpp
index 1e282ce74f2e..329b0a7968a2 100644
--- a/source/Plugins/Process/Utility/RegisterContextDummy.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDummy.cpp
@@ -129,7 +129,7 @@ RegisterContextDummy::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
}
uint32_t
-RegisterContextDummy::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+RegisterContextDummy::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num)
{
if (kind == eRegisterKindGeneric && num == LLDB_REGNUM_GENERIC_PC)
return 0;
diff --git a/source/Plugins/Process/Utility/RegisterContextDummy.h b/source/Plugins/Process/Utility/RegisterContextDummy.h
index ee8d5a134bbc..ddf466713048 100644
--- a/source/Plugins/Process/Utility/RegisterContextDummy.h
+++ b/source/Plugins/Process/Utility/RegisterContextDummy.h
@@ -60,7 +60,7 @@ public:
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
private:
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp b/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp
index 01c9bb4cde8f..185ba26944fe 100644
--- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp
@@ -62,27 +62,27 @@ RegisterContextFreeBSD_i386::RegisterContextFreeBSD_i386(const ArchSpec &target_
{
}
-RegisterContextFreeBSD_i386::~RegisterContextFreeBSD_i386()
-{
-}
-
size_t
-RegisterContextFreeBSD_i386::GetGPRSize()
+RegisterContextFreeBSD_i386::GetGPRSize() const
{
return sizeof(GPR);
}
const RegisterInfo *
-RegisterContextFreeBSD_i386::GetRegisterInfo()
+RegisterContextFreeBSD_i386::GetRegisterInfo() const
{
- switch (m_target_arch.GetCore())
+ switch (m_target_arch.GetMachine())
{
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
+ case llvm::Triple::x86:
return g_register_infos_i386;
default:
assert(false && "Unhandled target architecture.");
return NULL;
}
}
+
+uint32_t
+RegisterContextFreeBSD_i386::GetRegisterCount () const
+{
+ return static_cast<uint32_t> (sizeof (g_register_infos_i386) / sizeof (g_register_infos_i386 [0]));
+}
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h
index 4ec2ad3e9706..62792c02e2b9 100644
--- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h
@@ -13,17 +13,19 @@
#include "RegisterContextPOSIX.h"
class RegisterContextFreeBSD_i386
- : public RegisterInfoInterface
+ : public lldb_private::RegisterInfoInterface
{
public:
RegisterContextFreeBSD_i386(const lldb_private::ArchSpec &target_arch);
- virtual ~RegisterContextFreeBSD_i386();
size_t
- GetGPRSize();
+ GetGPRSize() const override;
const lldb_private::RegisterInfo *
- GetRegisterInfo();
+ GetRegisterInfo() const override;
+
+ uint32_t
+ GetRegisterCount () const override;
};
#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp b/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp
index 4714251fd2dc..c31b0ee7de53 100644
--- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp
@@ -71,20 +71,23 @@ RegisterContextFreeBSD_mips64::RegisterContextFreeBSD_mips64(const ArchSpec &tar
{
}
-RegisterContextFreeBSD_mips64::~RegisterContextFreeBSD_mips64()
-{
-}
-
size_t
-RegisterContextFreeBSD_mips64::GetGPRSize()
+RegisterContextFreeBSD_mips64::GetGPRSize() const
{
return sizeof(GPR);
}
const RegisterInfo *
-RegisterContextFreeBSD_mips64::GetRegisterInfo()
+RegisterContextFreeBSD_mips64::GetRegisterInfo() const
{
assert (m_target_arch.GetCore() == ArchSpec::eCore_mips64);
return g_register_infos_mips64;
}
+uint32_t
+RegisterContextFreeBSD_mips64::GetRegisterCount () const
+{
+ return static_cast<uint32_t> (sizeof (g_register_infos_mips64) / sizeof (g_register_infos_mips64 [0]));
+}
+
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h
index 9ee767955347..f9a3ce09c5b1 100644
--- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h
@@ -13,17 +13,19 @@
#include "RegisterContextPOSIX.h"
class RegisterContextFreeBSD_mips64:
- public RegisterInfoInterface
+ public lldb_private::RegisterInfoInterface
{
public:
RegisterContextFreeBSD_mips64(const lldb_private::ArchSpec &target_arch);
- virtual ~RegisterContextFreeBSD_mips64();
size_t
- GetGPRSize();
+ GetGPRSize() const override;
const lldb_private::RegisterInfo *
- GetRegisterInfo();
+ GetRegisterInfo() const override;
+
+ uint32_t
+ GetRegisterCount () const override;
};
#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp
index 2162aaffff18..257de7198590 100644
--- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp
@@ -67,10 +67,17 @@ struct dbreg {
#include "RegisterInfos_x86_64.h"
#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
+static std::vector<lldb_private::RegisterInfo>&
+GetSharedRegisterInfoVector ()
+{
+ static std::vector<lldb_private::RegisterInfo> register_infos;
+ return register_infos;
+}
+
static const RegisterInfo *
GetRegisterInfo_i386(const lldb_private::ArchSpec& arch)
{
- static std::vector<lldb_private::RegisterInfo> g_register_infos;
+ static std::vector<lldb_private::RegisterInfo> g_register_infos (GetSharedRegisterInfoVector ());
// Allocate RegisterInfo only once
if (g_register_infos.empty())
@@ -92,35 +99,61 @@ GetRegisterInfo_i386(const lldb_private::ArchSpec& arch)
return &g_register_infos[0];
}
-RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(const ArchSpec &target_arch) :
- RegisterInfoInterface(target_arch)
+static const RegisterInfo *
+PrivateGetRegisterInfoPtr (const lldb_private::ArchSpec& target_arch)
{
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::x86:
+ return GetRegisterInfo_i386 (target_arch);
+ case llvm::Triple::x86_64:
+ return g_register_infos_x86_64;
+ default:
+ assert(false && "Unhandled target architecture.");
+ return nullptr;
+ }
}
-RegisterContextFreeBSD_x86_64::~RegisterContextFreeBSD_x86_64()
+static uint32_t
+PrivateGetRegisterCount (const lldb_private::ArchSpec& target_arch)
+{
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::x86:
+ // This vector should have already been filled.
+ assert (!GetSharedRegisterInfoVector ().empty () && "i386 register info vector not filled.");
+ return static_cast<uint32_t> (GetSharedRegisterInfoVector().size ());
+ case llvm::Triple::x86_64:
+ return static_cast<uint32_t> (sizeof (g_register_infos_x86_64) / sizeof (g_register_infos_x86_64 [0]));
+ default:
+ assert(false && "Unhandled target architecture.");
+ return 0;
+ }
+}
+
+RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(const ArchSpec &target_arch) :
+ lldb_private::RegisterInfoInterface(target_arch),
+ m_register_info_p (PrivateGetRegisterInfoPtr (target_arch)),
+ m_register_count (PrivateGetRegisterCount (target_arch))
{
}
size_t
-RegisterContextFreeBSD_x86_64::GetGPRSize()
+RegisterContextFreeBSD_x86_64::GetGPRSize() const
{
return sizeof(GPR);
}
const RegisterInfo *
-RegisterContextFreeBSD_x86_64::GetRegisterInfo()
+RegisterContextFreeBSD_x86_64::GetRegisterInfo() const
{
- switch (m_target_arch.GetCore())
- {
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- return GetRegisterInfo_i386 (m_target_arch);
- case ArchSpec::eCore_x86_64_x86_64:
- return g_register_infos_x86_64;
- default:
- assert(false && "Unhandled target architecture.");
- return NULL;
- }
+ return m_register_info_p;
+}
+
+uint32_t
+RegisterContextFreeBSD_x86_64::GetRegisterCount () const
+{
+ return m_register_count;
}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h
index 731bb0ea6bcc..21fbdb4681b3 100644
--- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h
@@ -13,17 +13,23 @@
#include "RegisterContextPOSIX.h"
class RegisterContextFreeBSD_x86_64:
- public RegisterInfoInterface
+ public lldb_private::RegisterInfoInterface
{
public:
RegisterContextFreeBSD_x86_64(const lldb_private::ArchSpec &target_arch);
- virtual ~RegisterContextFreeBSD_x86_64();
size_t
- GetGPRSize();
+ GetGPRSize() const override;
const lldb_private::RegisterInfo *
- GetRegisterInfo();
+ GetRegisterInfo() const override;
+
+ uint32_t
+ GetRegisterCount () const override;
+
+private:
+ const lldb_private::RegisterInfo *m_register_info_p;
+ const uint32_t m_register_count;
};
#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextHistory.cpp b/source/Plugins/Process/Utility/RegisterContextHistory.cpp
index b7adb202ba49..3c370103629e 100644
--- a/source/Plugins/Process/Utility/RegisterContextHistory.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextHistory.cpp
@@ -130,7 +130,7 @@ RegisterContextHistory::WriteAllRegisterValues (const lldb::DataBufferSP &data_s
}
uint32_t
-RegisterContextHistory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+RegisterContextHistory::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num)
{
if (kind == eRegisterKindGeneric && num == LLDB_REGNUM_GENERIC_PC)
return 0;
diff --git a/source/Plugins/Process/Utility/RegisterContextHistory.h b/source/Plugins/Process/Utility/RegisterContextHistory.h
index 58e16080b52e..04842c62aff1 100644
--- a/source/Plugins/Process/Utility/RegisterContextHistory.h
+++ b/source/Plugins/Process/Utility/RegisterContextHistory.h
@@ -60,7 +60,7 @@ public:
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
private:
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index f209d538a712..b58e6bb607ed 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -163,15 +163,17 @@ RegisterContextLLDB::InitializeZerothFrame()
UnwindLogMsg ("using architectural default unwind method");
}
- // We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
+ // We require either a symbol or function in the symbols context to be successfully
+ // filled in or this context is of no use to us.
+ const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
if (pc_module_sp.get()
- && (pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+ && (pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, resolve_scope, m_sym_ctx) & resolve_scope))
{
m_sym_ctx_valid = true;
}
AddressRange addr_range;
- m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range);
+ m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range);
if (IsTrapHandlerSymbol (process, m_sym_ctx))
{
@@ -216,7 +218,7 @@ RegisterContextLLDB::InitializeZerothFrame()
UnwindPlan::RowSP active_row;
int cfa_offset = 0;
- int row_register_kind = -1;
+ lldb::RegisterKind row_register_kind = eRegisterKindGeneric;
if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
@@ -362,7 +364,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()
m_current_offset = -1;
m_current_offset_backed_up_one = -1;
addr_t cfa_regval = LLDB_INVALID_ADDRESS;
- int row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
+ RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0);
if (row.get())
{
@@ -417,18 +419,20 @@ RegisterContextLLDB::InitializeNonZerothFrame()
// a function/symbol because it is beyond the bounds of the correct
// function and there's no symbol there. ResolveSymbolContextForAddress
// will fail to find a symbol, back up the pc by 1 and re-search.
+ const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress (m_current_pc,
- eSymbolContextFunction | eSymbolContextSymbol,
+ resolve_scope,
m_sym_ctx, resolve_tail_call_address);
- // We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
- if ((resolved_scope & eSymbolContextSymbol) == eSymbolContextSymbol)
+ // We require either a symbol or function in the symbols context to be successfully
+ // filled in or this context is of no use to us.
+ if (resolve_scope & resolved_scope)
{
m_sym_ctx_valid = true;
}
AddressRange addr_range;
- if (!m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range))
+ if (!m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range))
{
m_sym_ctx_valid = false;
}
@@ -461,13 +465,12 @@ RegisterContextLLDB::InitializeNonZerothFrame()
temporary_pc.SetOffset(m_current_pc.GetOffset() - 1);
m_sym_ctx.Clear(false);
m_sym_ctx_valid = false;
- if ((pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+ uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
+
+ if (pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, resolve_scope, m_sym_ctx) & resolve_scope)
{
- m_sym_ctx_valid = true;
- }
- if (!m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range))
- {
- m_sym_ctx_valid = false;
+ if (m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range))
+ m_sym_ctx_valid = true;
}
}
@@ -510,7 +513,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()
UnwindPlan::RowSP active_row;
int cfa_offset = 0;
- int row_register_kind = -1;
+ RegisterKind row_register_kind = eRegisterKindGeneric;
// Try to get by with just the fast UnwindPlan if possible - the full UnwindPlan may be expensive to get
// (e.g. if we have to parse the entire eh_frame section of an ObjectFile for the first time.)
@@ -591,7 +594,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()
repeating_frames = true;
}
}
- if (repeating_frames && abi->FunctionCallsChangeCFA())
+ if (repeating_frames && abi && abi->FunctionCallsChangeCFA())
{
UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping");
m_frame_type = eNotAValidFrame;
@@ -707,7 +710,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// Note, if we have a symbol context & a symbol, we don't want to follow this code path. This is
// for jumping to memory regions without any information available.
- if ((!m_sym_ctx_valid || m_sym_ctx.symbol == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid())
+ if ((!m_sym_ctx_valid || (m_sym_ctx.function == NULL && m_sym_ctx.symbol == NULL)) && behaves_like_zeroth_frame && m_current_pc.IsValid())
{
uint32_t permissions;
addr_t current_pc_addr = m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr());
@@ -791,7 +794,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// Typically the NonCallSite UnwindPlan is the unwind created by inspecting the assembly language instructions
if (behaves_like_zeroth_frame)
{
- unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
+ 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))
{
if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo)
@@ -819,8 +822,8 @@ 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 (m_thread);
- if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo)
+ 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
// don't have any eh_frame instructions available.
@@ -889,7 +892,7 @@ RegisterContextLLDB::GetRegisterSet (size_t reg_set)
}
uint32_t
-RegisterContextLLDB::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+RegisterContextLLDB::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num)
{
return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num);
}
@@ -1415,7 +1418,7 @@ RegisterContextLLDB::TryFallbackUnwindPlan ()
// where frame 0 (the "next" frame) saved that and retrieve the value.
bool
-RegisterContextLLDB::ReadGPRValue (int register_kind, uint32_t regnum, addr_t &value)
+RegisterContextLLDB::ReadGPRValue (lldb::RegisterKind register_kind, uint32_t regnum, addr_t &value)
{
if (!IsValid())
return false;
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.h b/source/Plugins/Process/Utility/RegisterContextLLDB.h
index 0a60bfe382b5..d6ecfeb68caa 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.h
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.h
@@ -67,7 +67,7 @@ public:
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
bool
IsValid () const;
@@ -178,7 +178,7 @@ private:
// Get the contents of a general purpose (address-size) register for this frame
// (usually retrieved from the next frame)
bool
- ReadGPRValue (int register_kind, uint32_t regnum, lldb::addr_t &value);
+ ReadGPRValue (lldb::RegisterKind register_kind, uint32_t regnum, lldb::addr_t &value);
lldb::UnwindPlanSP
GetFastUnwindPlanForFrame ();
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp
new file mode 100644
index 000000000000..8c23e39ff013
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp
@@ -0,0 +1,89 @@
+//===-- RegisterContextLinux_arm64.cpp -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include <stddef.h>
+#include <vector>
+#include <cassert>
+
+#include "llvm/Support/Compiler.h"
+#include "lldb/lldb-defines.h"
+
+#include "RegisterContextLinux_arm64.h"
+
+// Based on RegisterContextDarwin_arm64.cpp
+#define GPR_OFFSET(idx) ((idx) * 8)
+#define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::GPR, reg))
+
+#define FPU_OFFSET(idx) ((idx) * 16 + sizeof (RegisterContextLinux_arm64::GPR))
+#define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::FPU, reg))
+
+#define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::EXC, reg) + sizeof (RegisterContextLinux_arm64::GPR) + sizeof (RegisterContextLinux_arm64::FPU))
+#define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::DBG, reg) + sizeof (RegisterContextLinux_arm64::GPR) + sizeof (RegisterContextLinux_arm64::FPU) + sizeof (RegisterContextLinux_arm64::EXC))
+
+#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextLinux_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL
+#define REG_CONTEXT_SIZE (sizeof (RegisterContextLinux_arm64::GPR) + sizeof (RegisterContextLinux_arm64::FPU) + sizeof (RegisterContextLinux_arm64::EXC))
+
+
+//-----------------------------------------------------------------------------
+// Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure.
+//-----------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_ARM64_STRUCT
+#include "RegisterInfos_arm64.h"
+#undef DECLARE_REGISTER_INFOS_ARM64_STRUCT
+
+static const lldb_private::RegisterInfo *
+GetRegisterInfoPtr (const lldb_private::ArchSpec &target_arch)
+{
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::aarch64:
+ return g_register_infos_arm64;
+ default:
+ assert(false && "Unhandled target architecture.");
+ return NULL;
+ }
+}
+
+static uint32_t
+GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch)
+{
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::aarch64:
+ return static_cast<uint32_t>(sizeof(g_register_infos_arm64) / sizeof(g_register_infos_arm64[0]));
+ default:
+ assert(false && "Unhandled target architecture.");
+ return 0;
+ }
+}
+
+RegisterContextLinux_arm64::RegisterContextLinux_arm64(const lldb_private::ArchSpec &target_arch) :
+ lldb_private::RegisterInfoInterface(target_arch),
+ m_register_info_p(GetRegisterInfoPtr(target_arch)),
+ m_register_info_count(GetRegisterInfoCount(target_arch))
+{
+}
+
+size_t
+RegisterContextLinux_arm64::GetGPRSize() const
+{
+ return sizeof(struct RegisterContextLinux_arm64::GPR);
+}
+
+const lldb_private::RegisterInfo *
+RegisterContextLinux_arm64::GetRegisterInfo() const
+{
+ return m_register_info_p;
+}
+
+uint32_t
+RegisterContextLinux_arm64::GetRegisterCount() const
+{
+ return m_register_info_count;
+}
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h b/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h
new file mode 100644
index 000000000000..a9a5a0985f25
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h
@@ -0,0 +1,81 @@
+//===-- RegisterContextLinux_arm64.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_RegisterContextLinux_arm64_H_
+#define liblldb_RegisterContextLinux_arm64_H_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
+
+class RegisterContextLinux_arm64
+ : public lldb_private::RegisterInfoInterface
+{
+public:
+ // based on RegisterContextDarwin_arm64.h
+ struct GPR
+ {
+ uint64_t x[29]; // x0-x28
+ uint64_t fp; // x29
+ uint64_t lr; // x30
+ uint64_t sp; // x31
+ uint64_t pc; // pc
+ uint32_t cpsr; // cpsr
+ };
+
+ // based on RegisterContextDarwin_arm64.h
+ struct VReg
+ {
+ uint8_t bytes[16];
+ };
+
+ // based on RegisterContextDarwin_arm64.h
+ struct FPU
+ {
+ VReg v[32];
+ uint32_t fpsr;
+ uint32_t fpcr;
+ };
+
+ // based on RegisterContextDarwin_arm64.h
+ struct EXC
+ {
+ uint64_t far; // Virtual Fault Address
+ uint32_t esr; // Exception syndrome
+ uint32_t exception; // number of arm exception token
+ };
+
+ // based on RegisterContextDarwin_arm64.h
+ struct DBG
+ {
+ uint64_t bvr[16];
+ uint64_t bcr[16];
+ uint64_t wvr[16];
+ uint64_t wcr[16];
+ uint64_t mdscr_el1;
+ };
+
+ RegisterContextLinux_arm64(const lldb_private::ArchSpec &target_arch);
+
+ size_t
+ GetGPRSize() const override;
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo() const override;
+
+ uint32_t
+ GetRegisterCount () const override;
+
+private:
+ const lldb_private::RegisterInfo *m_register_info_p;
+ uint32_t m_register_info_count;
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp
index 0828efbc6c3c..b9b9dca07be4 100644
--- a/source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp
@@ -34,11 +34,39 @@ struct GPR
uint32_t ss;
};
+struct FPR_i386
+{
+ uint16_t fctrl; // FPU Control Word (fcw)
+ uint16_t fstat; // FPU Status Word (fsw)
+ uint16_t ftag; // FPU Tag Word (ftw)
+ uint16_t fop; // Last Instruction Opcode (fop)
+ union
+ {
+ struct
+ {
+ uint64_t fip; // Instruction Pointer
+ uint64_t fdp; // Data Pointer
+ } x86_64;
+ struct
+ {
+ uint32_t fioff; // FPU IP Offset (fip)
+ uint32_t fiseg; // FPU IP Selector (fcs)
+ uint32_t fooff; // FPU Operand Pointer Offset (foo)
+ uint32_t foseg; // FPU Operand Pointer Selector (fos)
+ } i386_;// Added _ in the end to avoid error with gcc defining i386 in some cases
+ } ptr;
+ uint32_t mxcsr; // MXCSR Register State
+ uint32_t mxcsrmask; // MXCSR Mask
+ MMSReg stmm[8]; // 8*16 bytes for each FP-reg = 128 bytes
+ XMMReg xmm[8]; // 8*16 bytes for each XMM-reg = 128 bytes
+ uint32_t padding[56];
+};
+
struct UserArea
{
GPR regs; // General purpose registers.
int32_t fpvalid; // True if FPU is being used.
- FXSAVE i387; // FPU registers.
+ FPR_i386 i387; // FPU registers.
uint32_t tsize; // Text segment size.
uint32_t dsize; // Data segment size.
uint32_t ssize; // Stack segment size.
@@ -54,9 +82,11 @@ struct UserArea
uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7).
};
-#define DR_SIZE sizeof(UserArea::u_debugreg[0])
+#define DR_SIZE sizeof(((UserArea*)NULL)->u_debugreg[0])
+#define DR_0_OFFSET 0xFC
#define DR_OFFSET(reg_index) \
- (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index]))
+ (DR_0_OFFSET + (reg_index * 4))
+#define FPR_SIZE(reg) sizeof(((FPR_i386*)NULL)->reg)
//---------------------------------------------------------------------------
// Include RegisterInfos_i386 to declare our g_register_infos_i386 structure.
@@ -70,27 +100,28 @@ RegisterContextLinux_i386::RegisterContextLinux_i386(const ArchSpec &target_arch
{
}
-RegisterContextLinux_i386::~RegisterContextLinux_i386()
-{
-}
-
size_t
-RegisterContextLinux_i386::GetGPRSize()
+RegisterContextLinux_i386::GetGPRSize() const
{
return sizeof(GPR);
}
const RegisterInfo *
-RegisterContextLinux_i386::GetRegisterInfo()
+RegisterContextLinux_i386::GetRegisterInfo() const
{
- switch (m_target_arch.GetCore())
+ switch (m_target_arch.GetMachine())
{
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
+ case llvm::Triple::x86:
return g_register_infos_i386;
default:
assert(false && "Unhandled target architecture.");
return NULL;
}
}
+
+uint32_t
+RegisterContextLinux_i386::GetRegisterCount () const
+{
+ return static_cast<uint32_t> (sizeof (g_register_infos_i386) / sizeof (g_register_infos_i386 [0]));
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_i386.h b/source/Plugins/Process/Utility/RegisterContextLinux_i386.h
index 81afdbf8b1cf..f8b21fc8e87d 100644
--- a/source/Plugins/Process/POSIX/RegisterContextLinux_i386.h
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_i386.h
@@ -13,17 +13,19 @@
#include "RegisterContextPOSIX.h"
class RegisterContextLinux_i386
- : public RegisterInfoInterface
+ : public lldb_private::RegisterInfoInterface
{
public:
RegisterContextLinux_i386(const lldb_private::ArchSpec &target_arch);
- virtual ~RegisterContextLinux_i386();
size_t
- GetGPRSize();
+ GetGPRSize() const override;
const lldb_private::RegisterInfo *
- GetRegisterInfo();
+ GetRegisterInfo() const override;
+
+ uint32_t
+ GetRegisterCount () const override;
};
#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
index 5434ddfcf38b..74f016bd744d 100644
--- a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
@@ -69,7 +69,7 @@ struct UserArea
uint64_t fault_address; // Control register CR3.
};
-#define DR_SIZE sizeof(UserArea::u_debugreg[0])
+#define DR_SIZE sizeof(((UserArea*)NULL)->u_debugreg[0])
#define DR_OFFSET(reg_index) \
(LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index]))
@@ -80,10 +80,17 @@ struct UserArea
#include "RegisterInfos_x86_64.h"
#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
+static std::vector<lldb_private::RegisterInfo>&
+GetPrivateRegisterInfoVector ()
+{
+ static std::vector<lldb_private::RegisterInfo> g_register_infos;
+ return g_register_infos;
+}
+
static const RegisterInfo *
GetRegisterInfo_i386(const lldb_private::ArchSpec &arch)
{
- static std::vector<lldb_private::RegisterInfo> g_register_infos;
+ std::vector<lldb_private::RegisterInfo> &g_register_infos = GetPrivateRegisterInfoVector ();
// Allocate RegisterInfo only once
if (g_register_infos.empty())
@@ -105,35 +112,60 @@ GetRegisterInfo_i386(const lldb_private::ArchSpec &arch)
return &g_register_infos[0];
}
-RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) :
- RegisterInfoInterface(target_arch)
+static const RegisterInfo *
+GetRegisterInfoPtr (const ArchSpec &target_arch)
{
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::x86:
+ return GetRegisterInfo_i386 (target_arch);
+ case llvm::Triple::x86_64:
+ return g_register_infos_x86_64;
+ default:
+ assert(false && "Unhandled target architecture.");
+ return nullptr;
+ }
}
-RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64()
+static uint32_t
+GetRegisterInfoCount (const ArchSpec &target_arch)
+{
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::x86:
+ {
+ assert (!GetPrivateRegisterInfoVector ().empty () && "i386 register info not yet filled.");
+ return static_cast<uint32_t> (GetPrivateRegisterInfoVector ().size ());
+ }
+ case llvm::Triple::x86_64:
+ return static_cast<uint32_t> (sizeof (g_register_infos_x86_64) / sizeof (g_register_infos_x86_64 [0]));
+ default:
+ assert(false && "Unhandled target architecture.");
+ return 0;
+ }
+}
+
+RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) :
+ lldb_private::RegisterInfoInterface(target_arch),
+ m_register_info_p (GetRegisterInfoPtr (target_arch)),
+ m_register_info_count (GetRegisterInfoCount (target_arch))
{
}
size_t
-RegisterContextLinux_x86_64::GetGPRSize()
+RegisterContextLinux_x86_64::GetGPRSize() const
{
return sizeof(GPR);
}
const RegisterInfo *
-RegisterContextLinux_x86_64::GetRegisterInfo()
+RegisterContextLinux_x86_64::GetRegisterInfo() const
{
- switch (m_target_arch.GetCore())
- {
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- return GetRegisterInfo_i386 (m_target_arch);
- case ArchSpec::eCore_x86_64_x86_64:
- return g_register_infos_x86_64;
- default:
- assert(false && "Unhandled target architecture.");
- return NULL;
- }
+ return m_register_info_p;
}
+uint32_t
+RegisterContextLinux_x86_64::GetRegisterCount () const
+{
+ return m_register_info_count;
+}
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h
index 21c809b5dc33..7b6828661c1e 100644
--- a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h
@@ -13,17 +13,23 @@
#include "RegisterContextPOSIX.h"
class RegisterContextLinux_x86_64
- : public RegisterInfoInterface
+ : public lldb_private::RegisterInfoInterface
{
public:
RegisterContextLinux_x86_64(const lldb_private::ArchSpec &target_arch);
- virtual ~RegisterContextLinux_x86_64();
size_t
- GetGPRSize();
+ GetGPRSize() const override;
const lldb_private::RegisterInfo *
- GetRegisterInfo();
+ GetRegisterInfo() const override;
+
+ uint32_t
+ GetRegisterCount () const override;
+
+private:
+ const lldb_private::RegisterInfo *m_register_info_p;
+ uint32_t m_register_info_count;
};
#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
index 5b6d9fe9f3bb..e246e715de86 100644
--- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
@@ -149,7 +149,7 @@ 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(_MSC_VER) && !defined(__mips__)
+#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && !defined(_MSC_VER) && !defined(__mips__)
case sizeof (long double):
if (sizeof (long double) == sizeof(uint32_t))
{
@@ -199,7 +199,7 @@ RegisterContextMacOSXFrameBackchain::WriteAllRegisterValues (const lldb::DataBuf
uint32_t
-RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num)
{
return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num);
}
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
index 449e053e5ef1..505b8d44a27a 100644
--- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
@@ -63,7 +63,7 @@ public:
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
private:
UnwindMacOSXFrameBackchain::Cursor m_cursor;
diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/source/Plugins/Process/Utility/RegisterContextMemory.cpp
index 8c33a6814acc..40d00b1eed80 100644
--- a/source/Plugins/Process/Utility/RegisterContextMemory.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMemory.cpp
@@ -98,7 +98,7 @@ RegisterContextMemory::GetRegisterSet (size_t reg_set)
}
uint32_t
-RegisterContextMemory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+RegisterContextMemory::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num)
{
return m_reg_infos.ConvertRegisterKindToRegisterNumber (kind, num);
}
diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.h b/source/Plugins/Process/Utility/RegisterContextMemory.h
index 8bba52c627f3..9d97dfa723be 100644
--- a/source/Plugins/Process/Utility/RegisterContextMemory.h
+++ b/source/Plugins/Process/Utility/RegisterContextMemory.h
@@ -55,7 +55,7 @@ public:
GetRegisterSet (size_t reg_set);
virtual uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX.h b/source/Plugins/Process/Utility/RegisterContextPOSIX.h
index 600dae73b5b7..6ddd9cfe4c21 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX.h
@@ -15,6 +15,7 @@
// Other libraries and framework includes
#include "lldb/Core/ArchSpec.h"
#include "lldb/Target/RegisterContext.h"
+#include "RegisterInfoInterface.h"
//------------------------------------------------------------------------------
/// @class POSIXBreakpointProtocol
@@ -74,25 +75,5 @@ protected:
bool m_watchpoints_initialized;
};
-//------------------------------------------------------------------------------
-/// @class RegisterInfoInterface
-///
-/// @brief RegisterInfo interface to patch RegisterInfo structure for archs.
-class RegisterInfoInterface
-{
-public:
- RegisterInfoInterface(const lldb_private::ArchSpec& target_arch) : m_target_arch(target_arch) {}
- virtual ~RegisterInfoInterface () {}
-
- virtual size_t
- GetGPRSize () = 0;
-
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfo () = 0;
-
-public:
- lldb_private::ArchSpec m_target_arch;
-};
-
#endif // #ifndef liblldb_RegisterContextPOSIX_H_
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
new file mode 100644
index 000000000000..ea54a9ad9cf4
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
@@ -0,0 +1,299 @@
+//===-- RegisterContextPOSIX_arm64.cpp --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cstring>
+#include <errno.h>
+#include <stdint.h>
+
+#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_arm64.h"
+#include "Plugins/Process/elf-core/ProcessElfCore.h"
+
+// ARM64 general purpose registers.
+const uint32_t g_gpr_regnums_arm64[] =
+{
+ gpr_x0_arm64,
+ gpr_x1_arm64,
+ gpr_x2_arm64,
+ gpr_x3_arm64,
+ gpr_x4_arm64,
+ gpr_x5_arm64,
+ gpr_x6_arm64,
+ gpr_x7_arm64,
+ gpr_x8_arm64,
+ gpr_x9_arm64,
+ gpr_x10_arm64,
+ gpr_x11_arm64,
+ gpr_x12_arm64,
+ gpr_x13_arm64,
+ gpr_x14_arm64,
+ gpr_x15_arm64,
+ gpr_x16_arm64,
+ gpr_x17_arm64,
+ gpr_x18_arm64,
+ gpr_x19_arm64,
+ gpr_x20_arm64,
+ gpr_x21_arm64,
+ gpr_x22_arm64,
+ gpr_x23_arm64,
+ gpr_x24_arm64,
+ gpr_x25_arm64,
+ gpr_x26_arm64,
+ gpr_x27_arm64,
+ gpr_x28_arm64,
+ gpr_fp_arm64,
+ gpr_lr_arm64,
+ gpr_sp_arm64,
+ gpr_pc_arm64,
+ gpr_cpsr_arm64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, \
+ "g_gpr_regnums_arm64 has wrong number of register infos");
+
+// ARM64 floating point registers.
+static const uint32_t g_fpu_regnums_arm64[] =
+{
+ fpu_v0_arm64,
+ fpu_v1_arm64,
+ fpu_v2_arm64,
+ fpu_v3_arm64,
+ fpu_v4_arm64,
+ fpu_v5_arm64,
+ fpu_v6_arm64,
+ fpu_v7_arm64,
+ fpu_v8_arm64,
+ fpu_v9_arm64,
+ fpu_v10_arm64,
+ fpu_v11_arm64,
+ fpu_v12_arm64,
+ fpu_v13_arm64,
+ fpu_v14_arm64,
+ fpu_v15_arm64,
+ fpu_v16_arm64,
+ fpu_v17_arm64,
+ fpu_v18_arm64,
+ fpu_v19_arm64,
+ fpu_v20_arm64,
+ fpu_v21_arm64,
+ fpu_v22_arm64,
+ fpu_v23_arm64,
+ fpu_v24_arm64,
+ fpu_v25_arm64,
+ fpu_v26_arm64,
+ fpu_v27_arm64,
+ fpu_v28_arm64,
+ fpu_v29_arm64,
+ fpu_v30_arm64,
+ fpu_v31_arm64,
+ fpu_fpsr_arm64,
+ fpu_fpcr_arm64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, \
+ "g_fpu_regnums_arm64 has wrong number of register infos");
+
+// Number of register sets provided by this context.
+enum
+{
+ k_num_register_sets = 2
+};
+
+// Register sets for ARM64.
+static const lldb_private::RegisterSet
+g_reg_sets_arm64[k_num_register_sets] =
+{
+ { "General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 },
+ { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 }
+};
+
+bool RegisterContextPOSIX_arm64::IsGPR(unsigned reg)
+{
+ return reg <= m_reg_info.last_gpr; // GPR's come first.
+}
+
+bool RegisterContextPOSIX_arm64::IsFPR(unsigned reg)
+{
+ return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
+}
+
+RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ lldb_private::RegisterInfoInterface *register_info)
+ : lldb_private::RegisterContext(thread, concrete_frame_idx)
+{
+ m_register_info_ap.reset(register_info);
+
+ switch (register_info->m_target_arch.GetMachine())
+ {
+ case llvm::Triple::aarch64:
+ m_reg_info.num_registers = k_num_registers_arm64;
+ m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64;
+ m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64;
+ m_reg_info.last_gpr = k_last_gpr_arm64;
+ m_reg_info.first_fpr = k_first_fpr_arm64;
+ m_reg_info.last_fpr = k_last_fpr_arm64;
+ m_reg_info.first_fpr_v = fpu_v0_arm64;
+ m_reg_info.last_fpr_v = fpu_v31_arm64;
+ m_reg_info.gpr_flags = gpr_cpsr_arm64;
+ break;
+ default:
+ assert(false && "Unhandled target architecture.");
+ break;
+ }
+
+ ::memset(&m_fpr, 0, sizeof m_fpr);
+
+ // elf-core yet to support ReadFPR()
+ lldb::ProcessSP base = CalculateProcess();
+ if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
+ return;
+}
+
+RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64()
+{
+}
+
+void
+RegisterContextPOSIX_arm64::Invalidate()
+{
+}
+
+void
+RegisterContextPOSIX_arm64::InvalidateAllRegisters()
+{
+}
+
+unsigned
+RegisterContextPOSIX_arm64::GetRegisterOffset(unsigned reg)
+{
+ assert(reg < m_reg_info.num_registers && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_offset;
+}
+
+unsigned
+RegisterContextPOSIX_arm64::GetRegisterSize(unsigned reg)
+{
+ assert(reg < m_reg_info.num_registers && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_size;
+}
+
+size_t
+RegisterContextPOSIX_arm64::GetRegisterCount()
+{
+ size_t num_registers = m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers;
+ return num_registers;
+}
+
+size_t
+RegisterContextPOSIX_arm64::GetGPRSize()
+{
+ return m_register_info_ap->GetGPRSize ();
+}
+
+const lldb_private::RegisterInfo *
+RegisterContextPOSIX_arm64::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 lldb_private::RegisterInfo *
+RegisterContextPOSIX_arm64::GetRegisterInfoAtIndex(size_t reg)
+{
+ if (reg < m_reg_info.num_registers)
+ return &GetRegisterInfo()[reg];
+ else
+ return NULL;
+}
+
+size_t
+RegisterContextPOSIX_arm64::GetRegisterSetCount()
+{
+ size_t sets = 0;
+ for (size_t set = 0; set < k_num_register_sets; ++set)
+ {
+ if (IsRegisterSetAvailable(set))
+ ++sets;
+ }
+
+ return sets;
+}
+
+const lldb_private::RegisterSet *
+RegisterContextPOSIX_arm64::GetRegisterSet(size_t set)
+{
+ if (IsRegisterSetAvailable(set))
+ {
+ switch (m_register_info_ap->m_target_arch.GetMachine())
+ {
+ case llvm::Triple::aarch64:
+ return &g_reg_sets_arm64[set];
+ default:
+ assert(false && "Unhandled target architecture.");
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+const char *
+RegisterContextPOSIX_arm64::GetRegisterName(unsigned reg)
+{
+ assert(reg < m_reg_info.num_registers && "Invalid register offset.");
+ return GetRegisterInfo()[reg].name;
+}
+
+lldb::ByteOrder
+RegisterContextPOSIX_arm64::GetByteOrder()
+{
+ // Get the target process whose privileged thread was used for the register read.
+ lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
+ lldb_private::Process *process = CalculateProcess().get();
+
+ if (process)
+ byte_order = process->GetByteOrder();
+ return byte_order;
+}
+
+bool
+RegisterContextPOSIX_arm64::IsRegisterSetAvailable(size_t set_index)
+{
+ return set_index < k_num_register_sets;
+}
+
+
+// Used when parsing DWARF and EH frame information and any other
+// object file sections that contain register numbers in them.
+uint32_t
+RegisterContextPOSIX_arm64::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
+ uint32_t num)
+{
+ const uint32_t num_regs = GetRegisterCount();
+
+ assert (kind < lldb::kNumRegisterKinds);
+ for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx)
+ {
+ const lldb_private::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_arm64.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
new file mode 100644
index 000000000000..3639960ef3de
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
@@ -0,0 +1,272 @@
+//===-- RegisterContextPOSIX_arm64.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_arm64_H_
+#define liblldb_RegisterContextPOSIX_arm64_H_
+
+#include "lldb/Core/Log.h"
+#include "RegisterContextPOSIX.h"
+
+class ProcessMonitor;
+
+//---------------------------------------------------------------------------
+// Internal codes for all ARM64 registers.
+//---------------------------------------------------------------------------
+enum
+{
+ k_first_gpr_arm64,
+ gpr_x0_arm64 = k_first_gpr_arm64,
+ gpr_x1_arm64,
+ gpr_x2_arm64,
+ gpr_x3_arm64,
+ gpr_x4_arm64,
+ gpr_x5_arm64,
+ gpr_x6_arm64,
+ gpr_x7_arm64,
+ gpr_x8_arm64,
+ gpr_x9_arm64,
+ gpr_x10_arm64,
+ gpr_x11_arm64,
+ gpr_x12_arm64,
+ gpr_x13_arm64,
+ gpr_x14_arm64,
+ gpr_x15_arm64,
+ gpr_x16_arm64,
+ gpr_x17_arm64,
+ gpr_x18_arm64,
+ gpr_x19_arm64,
+ gpr_x20_arm64,
+ gpr_x21_arm64,
+ gpr_x22_arm64,
+ gpr_x23_arm64,
+ gpr_x24_arm64,
+ gpr_x25_arm64,
+ gpr_x26_arm64,
+ gpr_x27_arm64,
+ gpr_x28_arm64,
+ gpr_fp_arm64,
+ gpr_lr_arm64,
+ gpr_sp_arm64,
+ gpr_pc_arm64,
+ gpr_cpsr_arm64,
+
+ k_last_gpr_arm64 = gpr_cpsr_arm64,
+
+ k_first_fpr_arm64,
+ fpu_v0_arm64 = k_first_fpr_arm64,
+ fpu_v1_arm64,
+ fpu_v2_arm64,
+ fpu_v3_arm64,
+ fpu_v4_arm64,
+ fpu_v5_arm64,
+ fpu_v6_arm64,
+ fpu_v7_arm64,
+ fpu_v8_arm64,
+ fpu_v9_arm64,
+ fpu_v10_arm64,
+ fpu_v11_arm64,
+ fpu_v12_arm64,
+ fpu_v13_arm64,
+ fpu_v14_arm64,
+ fpu_v15_arm64,
+ fpu_v16_arm64,
+ fpu_v17_arm64,
+ fpu_v18_arm64,
+ fpu_v19_arm64,
+ fpu_v20_arm64,
+ fpu_v21_arm64,
+ fpu_v22_arm64,
+ fpu_v23_arm64,
+ fpu_v24_arm64,
+ fpu_v25_arm64,
+ fpu_v26_arm64,
+ fpu_v27_arm64,
+ fpu_v28_arm64,
+ fpu_v29_arm64,
+ fpu_v30_arm64,
+ fpu_v31_arm64,
+ fpu_fpsr_arm64,
+ fpu_fpcr_arm64,
+ k_last_fpr_arm64 = fpu_fpcr_arm64,
+
+ exc_far_arm64,
+ exc_esr_arm64,
+ exc_exception_arm64,
+
+ dbg_bvr0_arm64,
+ dbg_bvr1_arm64,
+ dbg_bvr2_arm64,
+ dbg_bvr3_arm64,
+ dbg_bvr4_arm64,
+ dbg_bvr5_arm64,
+ dbg_bvr6_arm64,
+ dbg_bvr7_arm64,
+ dbg_bvr8_arm64,
+ dbg_bvr9_arm64,
+ dbg_bvr10_arm64,
+ dbg_bvr11_arm64,
+ dbg_bvr12_arm64,
+ dbg_bvr13_arm64,
+ dbg_bvr14_arm64,
+ dbg_bvr15_arm64,
+ dbg_bcr0_arm64,
+ dbg_bcr1_arm64,
+ dbg_bcr2_arm64,
+ dbg_bcr3_arm64,
+ dbg_bcr4_arm64,
+ dbg_bcr5_arm64,
+ dbg_bcr6_arm64,
+ dbg_bcr7_arm64,
+ dbg_bcr8_arm64,
+ dbg_bcr9_arm64,
+ dbg_bcr10_arm64,
+ dbg_bcr11_arm64,
+ dbg_bcr12_arm64,
+ dbg_bcr13_arm64,
+ dbg_bcr14_arm64,
+ dbg_bcr15_arm64,
+ dbg_wvr0_arm64,
+ dbg_wvr1_arm64,
+ dbg_wvr2_arm64,
+ dbg_wvr3_arm64,
+ dbg_wvr4_arm64,
+ dbg_wvr5_arm64,
+ dbg_wvr6_arm64,
+ dbg_wvr7_arm64,
+ dbg_wvr8_arm64,
+ dbg_wvr9_arm64,
+ dbg_wvr10_arm64,
+ dbg_wvr11_arm64,
+ dbg_wvr12_arm64,
+ dbg_wvr13_arm64,
+ dbg_wvr14_arm64,
+ dbg_wvr15_arm64,
+ dbg_wcr0_arm64,
+ dbg_wcr1_arm64,
+ dbg_wcr2_arm64,
+ dbg_wcr3_arm64,
+ dbg_wcr4_arm64,
+ dbg_wcr5_arm64,
+ dbg_wcr6_arm64,
+ dbg_wcr7_arm64,
+ dbg_wcr8_arm64,
+ dbg_wcr9_arm64,
+ dbg_wcr10_arm64,
+ dbg_wcr11_arm64,
+ dbg_wcr12_arm64,
+ dbg_wcr13_arm64,
+ dbg_wcr14_arm64,
+ dbg_wcr15_arm64,
+
+ k_num_registers_arm64,
+ k_num_gpr_registers_arm64 = k_last_gpr_arm64 - k_first_gpr_arm64 + 1,
+ k_num_fpr_registers_arm64 = k_last_fpr_arm64 - k_first_fpr_arm64 + 1
+};
+
+class RegisterContextPOSIX_arm64
+ : public lldb_private::RegisterContext
+{
+public:
+ RegisterContextPOSIX_arm64 (lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ lldb_private::RegisterInfoInterface *register_info);
+
+ ~RegisterContextPOSIX_arm64();
+
+ 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:
+ struct RegInfo
+ {
+ uint32_t num_registers;
+ uint32_t num_gpr_registers;
+ uint32_t num_fpr_registers;
+
+ uint32_t last_gpr;
+ uint32_t first_fpr;
+ uint32_t last_fpr;
+
+ uint32_t first_fpr_v;
+ uint32_t last_fpr_v;
+
+ uint32_t gpr_flags;
+ };
+
+ // based on RegisterContextDarwin_arm64.h
+ struct VReg
+ {
+ uint8_t bytes[16];
+ };
+
+ // based on RegisterContextDarwin_arm64.h
+ struct FPU
+ {
+ VReg v[32];
+ uint32_t fpsr;
+ uint32_t fpcr;
+ };
+
+ uint64_t m_gpr_arm64[k_num_gpr_registers_arm64]; // 64-bit general purpose registers.
+ RegInfo m_reg_info;
+ struct RegisterContextPOSIX_arm64::FPU m_fpr; // floating-point registers including extended register sets.
+ std::unique_ptr<lldb_private::RegisterInfoInterface> 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_arm64_H_
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
index 45c99aec1657..cefedaec63c1 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
@@ -20,7 +20,6 @@
#include "lldb/Host/Endian.h"
#include "llvm/Support/Compiler.h"
-#include "ProcessPOSIX.h"
#include "RegisterContextPOSIX_mips64.h"
#include "Plugins/Process/elf-core/ProcessElfCore.h"
@@ -219,7 +218,7 @@ RegisterContextPOSIX_mips64::IsRegisterSetAvailable(size_t set_index)
// Used when parsing DWARF and EH frame information and any other
// object file sections that contain register numbers in them.
uint32_t
-RegisterContextPOSIX_mips64::ConvertRegisterKindToRegisterNumber(uint32_t kind,
+RegisterContextPOSIX_mips64::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
uint32_t num)
{
const uint32_t num_regs = GetRegisterCount();
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h
index a2a7d1f45271..991179bdec66 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h
@@ -73,7 +73,7 @@ class RegisterContextPOSIX_mips64
public:
RegisterContextPOSIX_mips64 (lldb_private::Thread &thread,
uint32_t concrete_frame_idx,
- RegisterInfoInterface *register_info);
+ lldb_private::RegisterInfoInterface *register_info);
~RegisterContextPOSIX_mips64();
@@ -108,11 +108,11 @@ public:
GetRegisterName(unsigned reg);
uint32_t
- ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
protected:
uint64_t m_gpr_mips64[k_num_gpr_registers_mips64]; // general purpose registers.
- std::unique_ptr<RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux)
+ std::unique_ptr<lldb_private::RegisterInfoInterface> 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
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
index 9ae541a6309b..2925a33a1690 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
@@ -20,7 +20,6 @@
#include "lldb/Host/Endian.h"
#include "llvm/Support/Compiler.h"
-#include "ProcessPOSIX.h"
#include "RegisterContext_x86.h"
#include "RegisterContextPOSIX_x86.h"
#include "Plugins/Process/elf-core/ProcessElfCore.h"
@@ -62,9 +61,10 @@ g_gpr_regnums_i386[] =
gpr_al_i386,
gpr_bl_i386,
gpr_cl_i386,
- gpr_dl_i386
+ gpr_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])) == k_num_gpr_registers_i386,
+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
@@ -103,9 +103,10 @@ g_fpu_regnums_i386[] =
fpu_xmm4_i386,
fpu_xmm5_i386,
fpu_xmm6_i386,
- fpu_xmm7_i386
+ fpu_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])) == k_num_fpr_registers_i386,
+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");
const uint32_t
@@ -118,9 +119,10 @@ g_avx_regnums_i386[] =
fpu_ymm4_i386,
fpu_ymm5_i386,
fpu_ymm6_i386,
- fpu_ymm7_i386
+ fpu_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])) == k_num_avx_registers_i386,
+static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 1 == k_num_avx_registers_i386,
" g_avx_regnums_i386 has wrong number of register infos");
static const
@@ -202,8 +204,9 @@ uint32_t g_gpr_regnums_x86_64[] =
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_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])) == k_num_gpr_registers_x86_64,
+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
@@ -250,9 +253,10 @@ g_fpu_regnums_x86_64[] =
fpu_xmm12_x86_64,
fpu_xmm13_x86_64,
fpu_xmm14_x86_64,
- fpu_xmm15_x86_64
+ fpu_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])) == k_num_fpr_registers_x86_64,
+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 const uint32_t
@@ -273,9 +277,10 @@ g_avx_regnums_x86_64[] =
fpu_ymm12_x86_64,
fpu_ymm13_x86_64,
fpu_ymm14_x86_64,
- fpu_ymm15_x86_64
+ fpu_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])) == k_num_avx_registers_x86_64,
+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 };
@@ -384,11 +389,9 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86(Thread &thread,
{
m_register_info_ap.reset(register_info);
- switch (register_info->m_target_arch.GetCore())
+ switch (register_info->m_target_arch.GetMachine())
{
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
+ case llvm::Triple::x86:
m_reg_info.num_registers = k_num_registers_i386;
m_reg_info.num_gpr_registers = k_num_gpr_registers_i386;
m_reg_info.num_fpr_registers = k_num_fpr_registers_i386;
@@ -407,7 +410,7 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86(Thread &thread,
m_reg_info.first_dr = dr0_i386;
m_reg_info.gpr_flags = gpr_eflags_i386;
break;
- case ArchSpec::eCore_x86_64_x86_64:
+ case llvm::Triple::x86_64:
m_reg_info.num_registers = k_num_registers_x86_64;
m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64;
m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64;
@@ -537,13 +540,11 @@ RegisterContextPOSIX_x86::GetRegisterSet(size_t set)
{
if (IsRegisterSetAvailable(set))
{
- switch (m_register_info_ap->m_target_arch.GetCore())
+ switch (m_register_info_ap->m_target_arch.GetMachine())
{
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
+ case llvm::Triple::x86:
return &g_reg_sets_i386[set];
- case ArchSpec::eCore_x86_64_x86_64:
+ case llvm::Triple::x86_64:
return &g_reg_sets_x86_64[set];
default:
assert(false && "Unhandled target architecture.");
@@ -647,8 +648,8 @@ RegisterContextPOSIX_x86::IsRegisterSetAvailable(size_t set_index)
// Used when parsing DWARF and EH frame information and any other
// object file sections that contain register numbers in them.
uint32_t
-RegisterContextPOSIX_x86::ConvertRegisterKindToRegisterNumber(uint32_t kind,
- uint32_t num)
+RegisterContextPOSIX_x86::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
+ uint32_t num)
{
const uint32_t num_regs = GetRegisterCount();
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
index 5e922025b830..4db7802e1b44 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
@@ -296,7 +296,7 @@ class RegisterContextPOSIX_x86
public:
RegisterContextPOSIX_x86 (lldb_private::Thread &thread,
uint32_t concrete_frame_idx,
- RegisterInfoInterface *register_info);
+ lldb_private::RegisterInfoInterface *register_info);
~RegisterContextPOSIX_x86();
@@ -331,7 +331,7 @@ public:
GetRegisterName(unsigned reg);
uint32_t
- ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
//---------------------------------------------------------------------------
// Note: prefer kernel definitions over user-land
@@ -428,7 +428,7 @@ protected:
FPR m_fpr; // floating-point registers including extended register sets.
IOVEC m_iovec; // wrapper for xsave.
YMM m_ymm_set; // copy of ymmh and xmm register halves.
- std::unique_ptr<RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux)
+ std::unique_ptr<lldb_private::RegisterInfoInterface> 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
diff --git a/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
index d35a5d095705..46dafa11d8f7 100644
--- a/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
@@ -167,7 +167,7 @@ RegisterContextThreadMemory::CopyFromRegisterContext (lldb::RegisterContextSP re
}
uint32_t
-RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num)
{
UpdateRegisterContext ();
if (m_reg_ctx_sp)
diff --git a/source/Plugins/Process/Utility/RegisterContextThreadMemory.h b/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
index 8d7a4b622fe8..161ef040e651 100644
--- a/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
+++ b/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
@@ -66,7 +66,7 @@ public:
CopyFromRegisterContext (lldb::RegisterContextSP context);
virtual uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
//------------------------------------------------------------------
// Subclasses can override these functions if desired
diff --git a/source/Plugins/Process/POSIX/RegisterContext_mips64.h b/source/Plugins/Process/Utility/RegisterContext_mips64.h
index dfd473d7cbec..dfd473d7cbec 100644
--- a/source/Plugins/Process/POSIX/RegisterContext_mips64.h
+++ b/source/Plugins/Process/Utility/RegisterContext_mips64.h
diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86.h b/source/Plugins/Process/Utility/RegisterContext_x86.h
index df3e1e5a84bf..6b3f6fb43e33 100644
--- a/source/Plugins/Process/POSIX/RegisterContext_x86.h
+++ b/source/Plugins/Process/Utility/RegisterContext_x86.h
@@ -34,8 +34,16 @@ enum
gcc_ecx_i386,
gcc_edx_i386,
gcc_ebx_i386,
- gcc_ebp_i386, // Warning: these are switched from dwarf values
- gcc_esp_i386, //
+
+ // on Darwin esp & ebp are reversed in the eh_frame section for i386 (versus dwarf's reg numbering).
+ // To be specific:
+ // i386+darwin eh_frame: 4 is ebp, 5 is esp
+ // i386+everyone else eh_frame: 4 is esp, 5 is ebp
+ // i386 dwarf: 4 is esp, 5 is ebp
+ // lldb will get the darwin-specific eh_frame reg numberings from debugserver instead of here so we
+ // only encode the 4 == esp, 5 == ebp numbers in this generic header.
+ gcc_esp_i386,
+ gcc_ebp_i386,
gcc_esi_i386,
gcc_edi_i386,
gcc_eip_i386,
@@ -411,7 +419,7 @@ struct FXSAVE
uint32_t fiseg; // FPU IP Selector (fcs)
uint32_t fooff; // FPU Operand Pointer Offset (foo)
uint32_t foseg; // FPU Operand Pointer Selector (fos)
- } i386;
+ } i386_;// Added _ in the end to avoid error with gcc defining i386 in some cases
} ptr;
uint32_t mxcsr; // MXCSR Register State
uint32_t mxcsrmask; // MXCSR Mask
diff --git a/source/Plugins/Process/Utility/RegisterInfoInterface.h b/source/Plugins/Process/Utility/RegisterInfoInterface.h
new file mode 100644
index 000000000000..382475f4523a
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterInfoInterface.h
@@ -0,0 +1,49 @@
+//===-- RegisterInfoInterface.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_RegisterInfoInterface_h
+#define lldb_RegisterInfoInterface_h
+
+#include "lldb/Core/ArchSpec.h"
+
+namespace lldb_private
+{
+
+ ///------------------------------------------------------------------------------
+ /// @class RegisterInfoInterface
+ ///
+ /// @brief RegisterInfo interface to patch RegisterInfo structure for archs.
+ ///------------------------------------------------------------------------------
+ class RegisterInfoInterface
+ {
+ public:
+ RegisterInfoInterface(const lldb_private::ArchSpec& target_arch) : m_target_arch(target_arch) {}
+ virtual ~RegisterInfoInterface () {}
+
+ virtual size_t
+ GetGPRSize () const = 0;
+
+ virtual const lldb_private::RegisterInfo *
+ GetRegisterInfo () const = 0;
+
+ virtual uint32_t
+ GetRegisterCount () const = 0;
+
+ const lldb_private::ArchSpec&
+ GetTargetArchitecture() const
+ { return m_target_arch; }
+
+ public:
+ // FIXME make private.
+ lldb_private::ArchSpec m_target_arch;
+ };
+
+}
+
+#endif
diff --git a/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/source/Plugins/Process/Utility/RegisterInfos_arm64.h
new file mode 100644
index 000000000000..1bb4e89c8f78
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterInfos_arm64.h
@@ -0,0 +1,347 @@
+//===-- RegisterInfos_arm64.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#ifdef DECLARE_REGISTER_INFOS_ARM64_STRUCT
+
+#include <stddef.h>
+
+#include "lldb/lldb-private.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+
+#include "ARM64_GCC_Registers.h"
+#include "ARM64_DWARF_Registers.h"
+
+#ifndef GPR_OFFSET
+#error GPR_OFFSET must be defined before including this header file
+#endif
+
+#ifndef GPR_OFFSET_NAME
+#error GPR_OFFSET_NAME must be defined before including this header file
+#endif
+
+#ifndef FPU_OFFSET
+#error FPU_OFFSET must be defined before including this header file
+#endif
+
+#ifndef FPU_OFFSET_NAME
+#error FPU_OFFSET_NAME must be defined before including this header file
+#endif
+
+#ifndef EXC_OFFSET_NAME
+#error EXC_OFFSET_NAME must be defined before including this header file
+#endif
+
+#ifndef DBG_OFFSET_NAME
+#error DBG_OFFSET_NAME must be defined before including this header file
+#endif
+
+#ifndef DEFINE_DBG
+#error DEFINE_DBG must be defined before including this header file
+#endif
+
+enum
+{
+ gpr_x0 = 0,
+ gpr_x1,
+ gpr_x2,
+ gpr_x3,
+ gpr_x4,
+ gpr_x5,
+ gpr_x6,
+ gpr_x7,
+ gpr_x8,
+ gpr_x9,
+ gpr_x10,
+ gpr_x11,
+ gpr_x12,
+ gpr_x13,
+ gpr_x14,
+ gpr_x15,
+ gpr_x16,
+ gpr_x17,
+ gpr_x18,
+ gpr_x19,
+ gpr_x20,
+ gpr_x21,
+ gpr_x22,
+ gpr_x23,
+ gpr_x24,
+ gpr_x25,
+ gpr_x26,
+ gpr_x27,
+ gpr_x28,
+ gpr_x29 = 29, gpr_fp = gpr_x29,
+ gpr_x30 = 30, gpr_lr = gpr_x30, gpr_ra = gpr_x30,
+ gpr_x31 = 31, gpr_sp = gpr_x31,
+ gpr_pc = 32,
+ gpr_cpsr,
+
+ fpu_v0,
+ fpu_v1,
+ fpu_v2,
+ fpu_v3,
+ fpu_v4,
+ fpu_v5,
+ fpu_v6,
+ fpu_v7,
+ fpu_v8,
+ fpu_v9,
+ fpu_v10,
+ fpu_v11,
+ fpu_v12,
+ fpu_v13,
+ fpu_v14,
+ fpu_v15,
+ fpu_v16,
+ fpu_v17,
+ fpu_v18,
+ fpu_v19,
+ fpu_v20,
+ fpu_v21,
+ fpu_v22,
+ fpu_v23,
+ fpu_v24,
+ fpu_v25,
+ fpu_v26,
+ fpu_v27,
+ fpu_v28,
+ fpu_v29,
+ fpu_v30,
+ fpu_v31,
+
+ fpu_fpsr,
+ fpu_fpcr,
+
+ exc_far,
+ exc_esr,
+ exc_exception,
+
+ dbg_bvr0,
+ dbg_bvr1,
+ dbg_bvr2,
+ dbg_bvr3,
+ dbg_bvr4,
+ dbg_bvr5,
+ dbg_bvr6,
+ dbg_bvr7,
+ dbg_bvr8,
+ dbg_bvr9,
+ dbg_bvr10,
+ dbg_bvr11,
+ dbg_bvr12,
+ dbg_bvr13,
+ dbg_bvr14,
+ dbg_bvr15,
+
+ dbg_bcr0,
+ dbg_bcr1,
+ dbg_bcr2,
+ dbg_bcr3,
+ dbg_bcr4,
+ dbg_bcr5,
+ dbg_bcr6,
+ dbg_bcr7,
+ dbg_bcr8,
+ dbg_bcr9,
+ dbg_bcr10,
+ dbg_bcr11,
+ dbg_bcr12,
+ dbg_bcr13,
+ dbg_bcr14,
+ dbg_bcr15,
+
+ dbg_wvr0,
+ dbg_wvr1,
+ dbg_wvr2,
+ dbg_wvr3,
+ dbg_wvr4,
+ dbg_wvr5,
+ dbg_wvr6,
+ dbg_wvr7,
+ dbg_wvr8,
+ dbg_wvr9,
+ dbg_wvr10,
+ dbg_wvr11,
+ dbg_wvr12,
+ dbg_wvr13,
+ dbg_wvr14,
+ dbg_wvr15,
+
+ dbg_wcr0,
+ dbg_wcr1,
+ dbg_wcr2,
+ dbg_wcr3,
+ dbg_wcr4,
+ dbg_wcr5,
+ dbg_wcr6,
+ dbg_wcr7,
+ dbg_wcr8,
+ dbg_wcr9,
+ dbg_wcr10,
+ dbg_wcr11,
+ dbg_wcr12,
+ dbg_wcr13,
+ dbg_wcr14,
+ dbg_wcr15,
+
+ k_num_registers
+};
+
+static lldb_private::RegisterInfo g_register_infos_arm64[] = {
+// General purpose registers
+// NAME ALT SZ OFFSET ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= ========== ===============
+{ "x0", NULL, 8, GPR_OFFSET(0), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x0, arm64_dwarf::x0, LLDB_INVALID_REGNUM, arm64_gcc::x0, gpr_x0 }, NULL, NULL},
+{ "x1", NULL, 8, GPR_OFFSET(1), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x1, arm64_dwarf::x1, LLDB_INVALID_REGNUM, arm64_gcc::x1, gpr_x1 }, NULL, NULL},
+{ "x2", NULL, 8, GPR_OFFSET(2), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x2, arm64_dwarf::x2, LLDB_INVALID_REGNUM, arm64_gcc::x2, gpr_x2 }, NULL, NULL},
+{ "x3", NULL, 8, GPR_OFFSET(3), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x3, arm64_dwarf::x3, LLDB_INVALID_REGNUM, arm64_gcc::x3, gpr_x3 }, NULL, NULL},
+{ "x4", NULL, 8, GPR_OFFSET(4), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x4, arm64_dwarf::x4, LLDB_INVALID_REGNUM, arm64_gcc::x4, gpr_x4 }, NULL, NULL},
+{ "x5", NULL, 8, GPR_OFFSET(5), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x5, arm64_dwarf::x5, LLDB_INVALID_REGNUM, arm64_gcc::x5, gpr_x5 }, NULL, NULL},
+{ "x6", NULL, 8, GPR_OFFSET(6), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x6, arm64_dwarf::x6, LLDB_INVALID_REGNUM, arm64_gcc::x6, gpr_x6 }, NULL, NULL},
+{ "x7", NULL, 8, GPR_OFFSET(7), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x7, arm64_dwarf::x7, LLDB_INVALID_REGNUM, arm64_gcc::x7, gpr_x7 }, NULL, NULL},
+{ "x8", NULL, 8, GPR_OFFSET(8), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x8, arm64_dwarf::x8, LLDB_INVALID_REGNUM, arm64_gcc::x8, gpr_x8 }, NULL, NULL},
+{ "x9", NULL, 8, GPR_OFFSET(9), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x9, arm64_dwarf::x9, LLDB_INVALID_REGNUM, arm64_gcc::x9, gpr_x9 }, NULL, NULL},
+{ "x10", NULL, 8, GPR_OFFSET(10), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x10, arm64_dwarf::x10, LLDB_INVALID_REGNUM, arm64_gcc::x10, gpr_x10 }, NULL, NULL},
+{ "x11", NULL, 8, GPR_OFFSET(11), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x11, arm64_dwarf::x11, LLDB_INVALID_REGNUM, arm64_gcc::x11, gpr_x11 }, NULL, NULL},
+{ "x12", NULL, 8, GPR_OFFSET(12), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x12, arm64_dwarf::x12, LLDB_INVALID_REGNUM, arm64_gcc::x12, gpr_x12 }, NULL, NULL},
+{ "x13", NULL, 8, GPR_OFFSET(13), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x13, arm64_dwarf::x13, LLDB_INVALID_REGNUM, arm64_gcc::x13, gpr_x13 }, NULL, NULL},
+{ "x14", NULL, 8, GPR_OFFSET(14), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x14, arm64_dwarf::x14, LLDB_INVALID_REGNUM, arm64_gcc::x14, gpr_x14 }, NULL, NULL},
+{ "x15", NULL, 8, GPR_OFFSET(15), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x15, arm64_dwarf::x15, LLDB_INVALID_REGNUM, arm64_gcc::x15, gpr_x15 }, NULL, NULL},
+{ "x16", NULL, 8, GPR_OFFSET(16), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x16, arm64_dwarf::x16, LLDB_INVALID_REGNUM, arm64_gcc::x16, gpr_x16 }, NULL, NULL},
+{ "x17", NULL, 8, GPR_OFFSET(17), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x17, arm64_dwarf::x17, LLDB_INVALID_REGNUM, arm64_gcc::x17, gpr_x17 }, NULL, NULL},
+{ "x18", NULL, 8, GPR_OFFSET(18), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x18, arm64_dwarf::x18, LLDB_INVALID_REGNUM, arm64_gcc::x18, gpr_x18 }, NULL, NULL},
+{ "x19", NULL, 8, GPR_OFFSET(19), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x19, arm64_dwarf::x19, LLDB_INVALID_REGNUM, arm64_gcc::x19, gpr_x19 }, NULL, NULL},
+{ "x20", NULL, 8, GPR_OFFSET(20), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x20, arm64_dwarf::x20, LLDB_INVALID_REGNUM, arm64_gcc::x20, gpr_x20 }, NULL, NULL},
+{ "x21", NULL, 8, GPR_OFFSET(21), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x21, arm64_dwarf::x21, LLDB_INVALID_REGNUM, arm64_gcc::x21, gpr_x21 }, NULL, NULL},
+{ "x22", NULL, 8, GPR_OFFSET(22), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x22, arm64_dwarf::x22, LLDB_INVALID_REGNUM, arm64_gcc::x22, gpr_x22 }, NULL, NULL},
+{ "x23", NULL, 8, GPR_OFFSET(23), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x23, arm64_dwarf::x23, LLDB_INVALID_REGNUM, arm64_gcc::x23, gpr_x23 }, NULL, NULL},
+{ "x24", NULL, 8, GPR_OFFSET(24), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x24, arm64_dwarf::x24, LLDB_INVALID_REGNUM, arm64_gcc::x24, gpr_x24 }, NULL, NULL},
+{ "x25", NULL, 8, GPR_OFFSET(25), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x25, arm64_dwarf::x25, LLDB_INVALID_REGNUM, arm64_gcc::x25, gpr_x25 }, NULL, NULL},
+{ "x26", NULL, 8, GPR_OFFSET(26), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x26, arm64_dwarf::x26, LLDB_INVALID_REGNUM, arm64_gcc::x26, gpr_x26 }, NULL, NULL},
+{ "x27", NULL, 8, GPR_OFFSET(27), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x27, arm64_dwarf::x27, LLDB_INVALID_REGNUM, arm64_gcc::x27, gpr_x27 }, NULL, NULL},
+{ "x28", NULL, 8, GPR_OFFSET(28), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x28, arm64_dwarf::x28, LLDB_INVALID_REGNUM, arm64_gcc::x28, gpr_x28 }, NULL, NULL},
+
+{ "fp", "x29", 8, GPR_OFFSET(29), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::fp, arm64_dwarf::fp, LLDB_REGNUM_GENERIC_FP, arm64_gcc::fp, gpr_fp }, NULL, NULL},
+{ "lr", "x30", 8, GPR_OFFSET(30), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::lr, arm64_dwarf::lr, LLDB_REGNUM_GENERIC_RA, arm64_gcc::lr, gpr_lr }, NULL, NULL},
+{ "sp", "x31", 8, GPR_OFFSET(31), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::sp, arm64_dwarf::sp, LLDB_REGNUM_GENERIC_SP, arm64_gcc::sp, gpr_sp }, NULL, NULL},
+{ "pc", NULL, 8, GPR_OFFSET(32), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, arm64_gcc::pc, gpr_pc }, NULL, NULL},
+
+{ "cpsr", NULL, 4, GPR_OFFSET_NAME(cpsr), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, arm64_gcc::cpsr, gpr_cpsr }, NULL, NULL},
+
+{ "v0", NULL, 16, FPU_OFFSET(0), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, arm64_gcc::v0, fpu_v0 }, NULL, NULL},
+{ "v1", NULL, 16, FPU_OFFSET(1), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, arm64_gcc::v1, fpu_v1 }, NULL, NULL},
+{ "v2", NULL, 16, FPU_OFFSET(2), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, arm64_gcc::v2, fpu_v2 }, NULL, NULL},
+{ "v3", NULL, 16, FPU_OFFSET(3), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, arm64_gcc::v3, fpu_v3 }, NULL, NULL},
+{ "v4", NULL, 16, FPU_OFFSET(4), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, arm64_gcc::v4, fpu_v4 }, NULL, NULL},
+{ "v5", NULL, 16, FPU_OFFSET(5), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, arm64_gcc::v5, fpu_v5 }, NULL, NULL},
+{ "v6", NULL, 16, FPU_OFFSET(6), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, arm64_gcc::v6, fpu_v6 }, NULL, NULL},
+{ "v7", NULL, 16, FPU_OFFSET(7), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, arm64_gcc::v7, fpu_v7 }, NULL, NULL},
+{ "v8", NULL, 16, FPU_OFFSET(8), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, arm64_gcc::v8, fpu_v8 }, NULL, NULL},
+{ "v9", NULL, 16, FPU_OFFSET(9), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, arm64_gcc::v9, fpu_v9 }, NULL, NULL},
+{ "v10", NULL, 16, FPU_OFFSET(10), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, arm64_gcc::v10, fpu_v10 }, NULL, NULL},
+{ "v11", NULL, 16, FPU_OFFSET(11), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, arm64_gcc::v11, fpu_v11 }, NULL, NULL},
+{ "v12", NULL, 16, FPU_OFFSET(12), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, arm64_gcc::v12, fpu_v12 }, NULL, NULL},
+{ "v13", NULL, 16, FPU_OFFSET(13), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, arm64_gcc::v13, fpu_v13 }, NULL, NULL},
+{ "v14", NULL, 16, FPU_OFFSET(14), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, arm64_gcc::v14, fpu_v14 }, NULL, NULL},
+{ "v15", NULL, 16, FPU_OFFSET(15), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, arm64_gcc::v15, fpu_v15 }, NULL, NULL},
+{ "v16", NULL, 16, FPU_OFFSET(16), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, arm64_gcc::v16, fpu_v16 }, NULL, NULL},
+{ "v17", NULL, 16, FPU_OFFSET(17), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, arm64_gcc::v17, fpu_v17 }, NULL, NULL},
+{ "v18", NULL, 16, FPU_OFFSET(18), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, arm64_gcc::v18, fpu_v18 }, NULL, NULL},
+{ "v19", NULL, 16, FPU_OFFSET(19), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, arm64_gcc::v19, fpu_v19 }, NULL, NULL},
+{ "v20", NULL, 16, FPU_OFFSET(20), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, arm64_gcc::v20, fpu_v20 }, NULL, NULL},
+{ "v21", NULL, 16, FPU_OFFSET(21), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, arm64_gcc::v21, fpu_v21 }, NULL, NULL},
+{ "v22", NULL, 16, FPU_OFFSET(22), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, arm64_gcc::v22, fpu_v22 }, NULL, NULL},
+{ "v23", NULL, 16, FPU_OFFSET(23), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, arm64_gcc::v23, fpu_v23 }, NULL, NULL},
+{ "v24", NULL, 16, FPU_OFFSET(24), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, arm64_gcc::v24, fpu_v24 }, NULL, NULL},
+{ "v25", NULL, 16, FPU_OFFSET(25), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, arm64_gcc::v25, fpu_v25 }, NULL, NULL},
+{ "v26", NULL, 16, FPU_OFFSET(26), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, arm64_gcc::v26, fpu_v26 }, NULL, NULL},
+{ "v27", NULL, 16, FPU_OFFSET(27), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, arm64_gcc::v27, fpu_v27 }, NULL, NULL},
+{ "v28", NULL, 16, FPU_OFFSET(28), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, arm64_gcc::v28, fpu_v28 }, NULL, NULL},
+{ "v29", NULL, 16, FPU_OFFSET(29), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, arm64_gcc::v29, fpu_v29 }, NULL, NULL},
+{ "v30", NULL, 16, FPU_OFFSET(30), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, arm64_gcc::v30, fpu_v30 }, NULL, NULL},
+{ "v31", NULL, 16, FPU_OFFSET(31), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, arm64_gcc::v31, fpu_v31 }, NULL, NULL},
+
+{ "fpsr", NULL, 4, FPU_OFFSET_NAME(fpsr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpsr }, NULL, NULL},
+{ "fpcr", NULL, 4, FPU_OFFSET_NAME(fpcr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpcr }, NULL, NULL},
+
+{ "far", NULL, 8, EXC_OFFSET_NAME(far), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, NULL, NULL},
+{ "esr", NULL, 4, EXC_OFFSET_NAME(esr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_esr }, NULL, NULL},
+{ "exception",NULL, 4, EXC_OFFSET_NAME(exception), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, NULL, NULL},
+
+{ DEFINE_DBG (bvr, 0) },
+{ DEFINE_DBG (bvr, 1) },
+{ DEFINE_DBG (bvr, 2) },
+{ DEFINE_DBG (bvr, 3) },
+{ DEFINE_DBG (bvr, 4) },
+{ DEFINE_DBG (bvr, 5) },
+{ DEFINE_DBG (bvr, 6) },
+{ DEFINE_DBG (bvr, 7) },
+{ DEFINE_DBG (bvr, 8) },
+{ DEFINE_DBG (bvr, 9) },
+{ DEFINE_DBG (bvr, 10) },
+{ DEFINE_DBG (bvr, 11) },
+{ DEFINE_DBG (bvr, 12) },
+{ DEFINE_DBG (bvr, 13) },
+{ DEFINE_DBG (bvr, 14) },
+{ DEFINE_DBG (bvr, 15) },
+
+{ DEFINE_DBG (bcr, 0) },
+{ DEFINE_DBG (bcr, 1) },
+{ DEFINE_DBG (bcr, 2) },
+{ DEFINE_DBG (bcr, 3) },
+{ DEFINE_DBG (bcr, 4) },
+{ DEFINE_DBG (bcr, 5) },
+{ DEFINE_DBG (bcr, 6) },
+{ DEFINE_DBG (bcr, 7) },
+{ DEFINE_DBG (bcr, 8) },
+{ DEFINE_DBG (bcr, 9) },
+{ DEFINE_DBG (bcr, 10) },
+{ DEFINE_DBG (bcr, 11) },
+{ DEFINE_DBG (bcr, 12) },
+{ DEFINE_DBG (bcr, 13) },
+{ DEFINE_DBG (bcr, 14) },
+{ DEFINE_DBG (bcr, 15) },
+
+{ DEFINE_DBG (wvr, 0) },
+{ DEFINE_DBG (wvr, 1) },
+{ DEFINE_DBG (wvr, 2) },
+{ DEFINE_DBG (wvr, 3) },
+{ DEFINE_DBG (wvr, 4) },
+{ DEFINE_DBG (wvr, 5) },
+{ DEFINE_DBG (wvr, 6) },
+{ DEFINE_DBG (wvr, 7) },
+{ DEFINE_DBG (wvr, 8) },
+{ DEFINE_DBG (wvr, 9) },
+{ DEFINE_DBG (wvr, 10) },
+{ DEFINE_DBG (wvr, 11) },
+{ DEFINE_DBG (wvr, 12) },
+{ DEFINE_DBG (wvr, 13) },
+{ DEFINE_DBG (wvr, 14) },
+{ DEFINE_DBG (wvr, 15) },
+
+{ DEFINE_DBG (wcr, 0) },
+{ DEFINE_DBG (wcr, 1) },
+{ DEFINE_DBG (wcr, 2) },
+{ DEFINE_DBG (wcr, 3) },
+{ DEFINE_DBG (wcr, 4) },
+{ DEFINE_DBG (wcr, 5) },
+{ DEFINE_DBG (wcr, 6) },
+{ DEFINE_DBG (wcr, 7) },
+{ DEFINE_DBG (wcr, 8) },
+{ DEFINE_DBG (wcr, 9) },
+{ DEFINE_DBG (wcr, 10) },
+{ DEFINE_DBG (wcr, 11) },
+{ DEFINE_DBG (wcr, 12) },
+{ DEFINE_DBG (wcr, 13) },
+{ DEFINE_DBG (wcr, 14) },
+{ DEFINE_DBG (wcr, 15) }
+};
+
+#endif // DECLARE_REGISTER_INFOS_ARM64_STRUCT
diff --git a/source/Plugins/Process/POSIX/RegisterInfos_i386.h b/source/Plugins/Process/Utility/RegisterInfos_i386.h
index 7c516568cd62..fa152b4147ce 100644
--- a/source/Plugins/Process/POSIX/RegisterInfos_i386.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_i386.h
@@ -8,6 +8,8 @@
//===---------------------------------------------------------------------===//
#include "llvm/Support/Compiler.h"
+#include <stddef.h>
+
#ifdef DECLARE_REGISTER_INFOS_I386_STRUCT
// Computes the offset of the given GPR in the user data area.
@@ -24,7 +26,9 @@
(LLVM_EXTENSION offsetof(YMM, regname))
// Number of bytes needed to represent a FPR.
+#if !defined(FPR_SIZE)
#define FPR_SIZE(reg) sizeof(((FXSAVE*)NULL)->reg)
+#endif
// Number of bytes needed to represent the i'th FP register.
#define FP_SIZE sizeof(((MMSReg*)NULL)->bytes)
@@ -37,7 +41,7 @@
// 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::reg), GPR_OFFSET(reg), eEncodingUint, \
+ { #reg, alt, sizeof(((GPR*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \
eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_i386 }, NULL, NULL }
#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \
@@ -129,10 +133,10 @@ g_register_infos_i386[] =
DEFINE_FPR(fstat, fstat, LLDB_INVALID_REGNUM, dwarf_fstat_i386, LLDB_INVALID_REGNUM, gdb_fstat_i386),
DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftag_i386),
DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop_i386),
- DEFINE_FPR(fiseg, ptr.i386.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_i386),
- DEFINE_FPR(fioff, ptr.i386.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_i386),
- DEFINE_FPR(foseg, ptr.i386.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_i386),
- DEFINE_FPR(fooff, ptr.i386.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_i386),
+ DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_i386),
+ DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_i386),
+ DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_i386),
+ DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_i386),
DEFINE_FPR(mxcsr, mxcsr, LLDB_INVALID_REGNUM, dwarf_mxcsr_i386, LLDB_INVALID_REGNUM, gdb_mxcsr_i386),
DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
diff --git a/source/Plugins/Process/POSIX/RegisterInfos_mips64.h b/source/Plugins/Process/Utility/RegisterInfos_mips64.h
index 13526e3680b7..187b8e98332e 100644
--- a/source/Plugins/Process/POSIX/RegisterInfos_mips64.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_mips64.h
@@ -7,6 +7,8 @@
//
//===---------------------------------------------------------------------===//
+#include <stddef.h>
+
// Computes the offset of the given GPR in the user data area.
#define GPR_OFFSET(regname) \
(offsetof(GPR, regname))
@@ -15,7 +17,7 @@
// 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::reg), GPR_OFFSET(reg), eEncodingUint, \
+ { #reg, alt, sizeof(((GPR*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \
eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL }
static RegisterInfo
diff --git a/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
index 86abdba68db6..c4dc6041ce43 100644
--- a/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
@@ -8,6 +8,8 @@
//===---------------------------------------------------------------------===//
#include "llvm/Support/Compiler.h"
+#include <stddef.h>
+
// Computes the offset of the given GPR in the user data area.
#define GPR_OFFSET(regname) \
(LLVM_EXTENSION offsetof(GPR, regname))
@@ -39,7 +41,7 @@
// 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::reg), GPR_OFFSET(reg), eEncodingUint, \
+ { #reg, alt, sizeof(((GPR*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \
eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_x86_64 }, NULL, NULL }
#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \
@@ -175,10 +177,10 @@ g_register_infos_x86_64[] =
DEFINE_FPR(fstat, fstat, gcc_dwarf_fstat_x86_64, gcc_dwarf_fstat_x86_64, LLDB_INVALID_REGNUM, gdb_fstat_x86_64),
DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftag_x86_64),
DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop_x86_64),
- DEFINE_FPR(fiseg, ptr.i386.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_x86_64),
- DEFINE_FPR(fioff, ptr.i386.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_x86_64),
- DEFINE_FPR(foseg, ptr.i386.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_x86_64),
- DEFINE_FPR(fooff, ptr.i386.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_x86_64),
+ DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_x86_64),
+ DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_x86_64),
+ DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_x86_64),
+ DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_x86_64),
DEFINE_FPR(mxcsr, mxcsr, gcc_dwarf_mxcsr_x86_64, gcc_dwarf_mxcsr_x86_64, LLDB_INVALID_REGNUM, gdb_mxcsr_x86_64),
DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
@@ -343,10 +345,10 @@ do {
UPDATE_FPR_INFO(fstat, fstat);
UPDATE_FPR_INFO(ftag, ftag);
UPDATE_FPR_INFO(fop, fop);
- UPDATE_FPR_INFO(fiseg, ptr.i386.fiseg);
- UPDATE_FPR_INFO(fioff, ptr.i386.fioff);
- UPDATE_FPR_INFO(fooff, ptr.i386.fooff);
- UPDATE_FPR_INFO(foseg, ptr.i386.foseg);
+ UPDATE_FPR_INFO(fiseg, ptr.i386_.fiseg);
+ UPDATE_FPR_INFO(fioff, ptr.i386_.fioff);
+ UPDATE_FPR_INFO(fooff, ptr.i386_.fooff);
+ UPDATE_FPR_INFO(foseg, ptr.i386_.foseg);
UPDATE_FPR_INFO(mxcsr, mxcsr);
UPDATE_FPR_INFO(mxcsrmask, mxcsrmask);
diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 51d2052e1931..0e3e559aef5c 100644
--- a/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -363,20 +363,30 @@ StopInfoMachException::CreateStopReasonWithMachException
if (exc_code == 1) // EXC_I386_SGL
{
if (!exc_sub_code)
- return StopInfo::CreateStopReasonToTrace(thread);
-
- // It's a watchpoint, then.
- // The exc_sub_code indicates the data break address.
- lldb::WatchpointSP wp_sp;
- if (target)
- wp_sp = target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code);
- if (wp_sp && wp_sp->IsEnabled())
{
- // Debugserver may piggyback the hardware index of the fired watchpoint in the exception data.
- // Set the hardware index if that's the case.
- if (exc_data_count >=3)
- wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
- return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
+ // This looks like a plain trap.
+ // Have to check if there is a breakpoint here as well. When you single-step onto a trap,
+ // the single step stops you not to trap. Since we also do that check below, let's just use
+ // that logic.
+ is_actual_breakpoint = true;
+ is_trace_if_actual_breakpoint_missing = true;
+ }
+ else
+ {
+
+ // It's a watchpoint, then.
+ // The exc_sub_code indicates the data break address.
+ lldb::WatchpointSP wp_sp;
+ if (target)
+ wp_sp = target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code);
+ if (wp_sp && wp_sp->IsEnabled())
+ {
+ // Debugserver may piggyback the hardware index of the fired watchpoint in the exception data.
+ // Set the hardware index if that's the case.
+ if (exc_data_count >=3)
+ wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
+ return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
+ }
}
}
else if (exc_code == 2 || // EXC_I386_BPT
@@ -429,6 +439,38 @@ StopInfoMachException::CreateStopReasonWithMachException
}
break;
+ case llvm::Triple::aarch64:
+ {
+ if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT
+ {
+ // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0 is set
+ return StopInfo::CreateStopReasonToTrace(thread);
+ }
+ if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
+ {
+ // It's a watchpoint, then, if the exc_sub_code indicates a known/enabled
+ // data break address from our watchpoint list.
+ lldb::WatchpointSP wp_sp;
+ if (target)
+ wp_sp = target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code);
+ if (wp_sp && wp_sp->IsEnabled())
+ {
+ // Debugserver may piggyback the hardware index of the fired watchpoint in the exception data.
+ // Set the hardware index if that's the case.
+ if (exc_data_count >= 3)
+ 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);
+ }
+ // It looks like exc_sub_code has the 4 bytes of the instruction that triggered the
+ // exception, i.e. our breakpoint opcode
+ is_actual_breakpoint = exc_code == 1;
+ break;
+ }
+
default:
break;
}
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 5db08e5c26de..37fd4f489552 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -347,7 +347,7 @@ bool
UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, uint32_t starting_frame_num, bool pc_reg)
{
int64_t frame_num = starting_frame_num;
- if (frame_num >= m_frames.size())
+ if (static_cast<size_t>(frame_num) >= m_frames.size())
return false;
// Never interrogate more than one level while looking for the saved pc value. If the value
diff --git a/source/Plugins/Process/Utility/lldb-x86-register-enums.h b/source/Plugins/Process/Utility/lldb-x86-register-enums.h
new file mode 100644
index 000000000000..c4706d567b70
--- /dev/null
+++ b/source/Plugins/Process/Utility/lldb-x86-register-enums.h
@@ -0,0 +1,292 @@
+//===-- lldb-x86-register-enums.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_x86_register_enums_h
+#define lldb_x86_register_enums_h
+
+namespace lldb_private
+{
+
+ //---------------------------------------------------------------------------
+ // 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
+ };
+
+}
+
+#endif // #ifndef lldb_x86_register_enums_h
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 7ea5c89e7df4..566816783c7e 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -17,12 +17,17 @@
#include "lldb/Core/Section.h"
#include "lldb/Core/State.h"
#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Log.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/DynamicLoader.h"
-#include "ProcessPOSIXLog.h"
+#include "lldb/Target/UnixSignals.h"
+
+#include "llvm/Support/ELF.h"
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
+#include "Plugins/Process/Utility/FreeBSDSignals.h"
+#include "Plugins/Process/Utility/LinuxSignals.h"
// Project includes
#include "ProcessElfCore.h"
@@ -54,8 +59,25 @@ lldb::ProcessSP
ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file)
{
lldb::ProcessSP process_sp;
- if (crash_file)
- process_sp.reset(new ProcessElfCore (target, listener, *crash_file));
+ if (crash_file)
+ {
+ // Read enough data for a ELF32 header or ELF64 header
+ const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr);
+
+ lldb::DataBufferSP data_sp (crash_file->ReadFileContents(0, header_size));
+ if (data_sp && data_sp->GetByteSize() == header_size &&
+ elf::ELFHeader::MagicBytesMatch (data_sp->GetBytes()))
+ {
+ elf::ELFHeader elf_header;
+ DataExtractor data(data_sp, lldb::eByteOrderLittle, 4);
+ lldb::offset_t data_offset = 0;
+ if (elf_header.Parse(data, &data_offset))
+ {
+ if (elf_header.e_type == llvm::ELF::ET_CORE)
+ process_sp.reset(new ProcessElfCore (target, listener, *crash_file));
+ }
+ }
+ }
return process_sp;
}
@@ -66,7 +88,7 @@ ProcessElfCore::CanDebug(Target &target, bool plugin_specified_by_name)
if (!m_core_module_sp && m_core_file.Exists())
{
ModuleSpec core_module_spec(m_core_file, target.GetArchitecture());
- Error error (ModuleList::GetSharedModule (core_module_spec, m_core_module_sp,
+ Error error (ModuleList::GetSharedModule (core_module_spec, m_core_module_sp,
NULL, NULL, NULL));
if (m_core_module_sp)
{
@@ -87,6 +109,7 @@ ProcessElfCore::ProcessElfCore(Target& target, Listener &listener,
m_core_module_sp (),
m_core_file (core_file),
m_dyld_plugin_name (),
+ m_os(llvm::Triple::UnknownOS),
m_thread_data_valid(false),
m_thread_data(),
m_core_aranges ()
@@ -154,21 +177,21 @@ ProcessElfCore::DoLoadCore ()
Error error;
if (!m_core_module_sp)
{
- error.SetErrorString ("invalid core module");
+ error.SetErrorString ("invalid core module");
return error;
}
ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile());
if (core == NULL)
{
- error.SetErrorString ("invalid core object file");
+ error.SetErrorString ("invalid core object file");
return error;
}
const uint32_t num_segments = core->GetProgramHeaderCount();
if (num_segments == 0)
{
- error.SetErrorString ("core file has no sections");
+ error.SetErrorString ("core file has no sections");
return error;
}
@@ -209,7 +232,25 @@ ProcessElfCore::DoLoadCore ()
// it to match the core file which is always single arch.
ArchSpec arch (m_core_module_sp->GetArchitecture());
if (arch.IsValid())
- m_target.SetArchitecture(arch);
+ m_target.SetArchitecture(arch);
+
+ switch (m_os)
+ {
+ case llvm::Triple::FreeBSD:
+ {
+ static UnixSignalsSP s_freebsd_signals_sp(new FreeBSDSignals ());
+ SetUnixSignals(s_freebsd_signals_sp);
+ break;
+ }
+ case llvm::Triple::Linux:
+ {
+ static UnixSignalsSP s_linux_signals_sp(new process_linux::LinuxSignals ());
+ SetUnixSignals(s_linux_signals_sp);
+ break;
+ }
+ default:
+ break;
+ }
return error;
}
@@ -324,13 +365,17 @@ void
ProcessElfCore::Clear()
{
m_thread_list.Clear();
+ m_os = llvm::Triple::UnknownOS;
+
+ static UnixSignalsSP s_default_unix_signals_sp(new UnixSignals());
+ SetUnixSignals(s_default_unix_signals_sp);
}
void
ProcessElfCore::Initialize()
{
static bool g_initialized = false;
-
+
if (g_initialized == false)
{
g_initialized = true;
@@ -378,7 +423,7 @@ ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
arch.GetMachine() == llvm::Triple::x86_64);
int pr_version = data.GetU32(&offset);
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ Log *log (GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
if (log)
{
if (pr_version > 1)
@@ -395,7 +440,7 @@ ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
offset += 4; // pr_pid
if (lp64)
offset += 4;
-
+
size_t len = data.GetByteSize() - offset;
thread_data.gpregset = DataExtractor(data, offset, len);
}
@@ -421,7 +466,7 @@ ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data)
/// a) Each thread context(2 or more NOTE entries) contained in its own segment (PT_NOTE)
/// b) All thread context is stored in a single segment(PT_NOTE).
/// This case is little tricker since while parsing we have to find where the
-/// new thread starts. The current implementation marks beginning of
+/// new thread starts. The current implementation marks beginning of
/// new thread when it finds NT_PRSTATUS or NT_PRPSINFO NOTE entry.
/// For case (b) there may be either one NT_PRPSINFO per thread, or a single
/// one that applies to all threads (depending on the platform type).
@@ -468,6 +513,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
DataExtractor note_data (segment_data, note_start, note_size);
if (note.n_name == "FreeBSD")
{
+ m_os = llvm::Triple::FreeBSD;
switch (note.n_type)
{
case NT_FREEBSD_PRSTATUS:
@@ -553,4 +599,3 @@ ProcessElfCore::GetAuxvData()
lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(start, len));
return buffer;
}
-
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.h b/source/Plugins/Process/elf-core/ProcessElfCore.h
index 1c1ed98ce17a..2fc2e4ee7949 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -37,45 +37,45 @@ public:
// Constructors and Destructors
//------------------------------------------------------------------
static lldb::ProcessSP
- CreateInstance (lldb_private::Target& target,
- lldb_private::Listener &listener,
+ CreateInstance (lldb_private::Target& target,
+ lldb_private::Listener &listener,
const lldb_private::FileSpec *crash_file_path);
-
+
static void
Initialize();
-
+
static void
Terminate();
-
+
static lldb_private::ConstString
GetPluginNameStatic();
-
+
static const char *
GetPluginDescriptionStatic();
-
+
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- ProcessElfCore(lldb_private::Target& target,
+ ProcessElfCore(lldb_private::Target& target,
lldb_private::Listener &listener,
const lldb_private::FileSpec &core_file);
-
+
virtual
~ProcessElfCore();
-
+
//------------------------------------------------------------------
// Check if a given Process
//------------------------------------------------------------------
virtual bool
CanDebug (lldb_private::Target &target,
bool plugin_specified_by_name);
-
+
//------------------------------------------------------------------
// Creating a new process, or attaching to an existing one
//------------------------------------------------------------------
virtual lldb_private::Error
DoLoadCore ();
-
+
virtual lldb_private::DynamicLoader *
GetDynamicLoader ();
@@ -84,19 +84,19 @@ public:
//------------------------------------------------------------------
virtual lldb_private::ConstString
GetPluginName();
-
+
virtual uint32_t
GetPluginVersion();
-
+
//------------------------------------------------------------------
// Process Control
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
virtual lldb_private::Error
DoDestroy ();
-
+
virtual void
RefreshStateAfterStop();
-
+
//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------
@@ -108,10 +108,10 @@ public:
//------------------------------------------------------------------
virtual size_t
ReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
-
+
virtual size_t
DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
-
+
virtual lldb::addr_t
GetImageInfoAddress ();
@@ -120,16 +120,16 @@ public:
// Returns AUXV structure found in the core file
const lldb::DataBufferSP
- GetAuxvData();
+ GetAuxvData() override;
protected:
void
Clear ( );
-
+
virtual bool
- UpdateThreadList (lldb_private::ThreadList &old_thread_list,
+ UpdateThreadList (lldb_private::ThreadList &old_thread_list,
lldb_private::ThreadList &new_thread_list);
-
+
private:
//------------------------------------------------------------------
// For ProcessElfCore only
@@ -142,6 +142,8 @@ private:
std::string m_dyld_plugin_name;
DISALLOW_COPY_AND_ASSIGN (ProcessElfCore);
+ llvm::Triple::OSType m_os;
+
// True if m_thread_contexts contains valid entries
bool m_thread_data_valid;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
index b95a51130ca7..fbf397b933cc 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
@@ -21,13 +21,9 @@ RegisterContextCorePOSIX_mips64::RegisterContextCorePOSIX_mips64(Thread &thread,
const DataExtractor &fpregset)
: RegisterContextPOSIX_mips64(thread, 0, register_info)
{
- size_t i;
- lldb::offset_t offset = 0;
-
- for (i = 0; i < k_num_gpr_registers_mips64; i++)
- {
- m_reg[i] = gpregset.GetU64(&offset);
- }
+ m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize()));
+ m_gpr.SetData(m_gpr_buffer);
+ m_gpr.SetByteOrder(gpregset.GetByteOrder());
}
RegisterContextCorePOSIX_mips64::~RegisterContextCorePOSIX_mips64()
@@ -63,10 +59,14 @@ RegisterContextCorePOSIX_mips64::WriteFPR()
bool
RegisterContextCorePOSIX_mips64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
{
- int reg_num = reg_info->byte_offset / 8;
- assert(reg_num < k_num_gpr_registers_mips64);
- value = m_reg[reg_num];
- return true;
+ lldb::offset_t offset = reg_info->byte_offset;
+ uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
+ if (offset == reg_info->byte_offset + reg_info->byte_size)
+ {
+ value = v;
+ return true;
+ }
+ return false;
}
bool
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
index 92e486bf2235..ca29d4f0febd 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
@@ -10,14 +10,15 @@
#ifndef liblldb_RegisterContextCorePOSIX_mips64_H_
#define liblldb_RegisterContextCorePOSIX_mips64_H_
-#include "Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
class RegisterContextCorePOSIX_mips64 :
public RegisterContextPOSIX_mips64
{
public:
RegisterContextCorePOSIX_mips64 (lldb_private::Thread &thread,
- RegisterInfoInterface *register_info,
+ lldb_private::RegisterInfoInterface *register_info,
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);
@@ -52,7 +53,8 @@ protected:
WriteFPR();
private:
- uint64_t m_reg[40];
+ lldb::DataBufferSP m_gpr_buffer;
+ lldb_private::DataExtractor m_gpr;
};
#endif // #ifndef liblldb_RegisterContextCorePOSIX_mips64_H_
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
index d4ea14fab7b1..ac0f49c3db52 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
@@ -10,14 +10,14 @@
#ifndef liblldb_RegisterContextCorePOSIX_x86_64_H_
#define liblldb_RegisterContextCorePOSIX_x86_64_H_
-#include "Plugins/Process/POSIX/RegisterContextPOSIX_x86.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
class RegisterContextCorePOSIX_x86_64 :
public RegisterContextPOSIX_x86
{
public:
RegisterContextCorePOSIX_x86_64 (lldb_private::Thread &thread,
- RegisterInfoInterface *register_info,
+ lldb_private::RegisterInfoInterface *register_info,
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index cadcf53ca543..d9f6cc04a343 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -8,11 +8,11 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Unwind.h"
-#include "ProcessPOSIXLog.h"
#include "ThreadElfCore.h"
#include "ProcessElfCore.h"
@@ -74,7 +74,7 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
{
RegisterContextSP reg_ctx_sp;
uint32_t concrete_frame_idx = 0;
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ Log *log (GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
if (frame)
concrete_frame_idx = frame->GetConcreteFrameIndex ();
@@ -108,7 +108,7 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
}
break;
}
-
+
case llvm::Triple::Linux:
{
switch (arch.GetMachine())
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h
index 2661edfa50cd..f1f00cf019b3 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.h
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.h
@@ -40,7 +40,7 @@ struct ELFLinuxPrStatus
int32_t si_errno;
int16_t pr_cursig;
-
+
uint64_t pr_sigpend;
uint64_t pr_sighold;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 72600d835934..1f4dd93976ec 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -22,14 +22,21 @@
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/Socket.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Target/Process.h"
// Project includes
#include "ProcessGDBRemoteLog.h"
-#define DEBUGSERVER_BASENAME "debugserver"
+#if defined(__APPLE__)
+# define DEBUGSERVER_BASENAME "debugserver"
+#else
+# define DEBUGSERVER_BASENAME "lldb-gdbserver"
+#endif
using namespace lldb;
using namespace lldb_private;
@@ -321,6 +328,7 @@ GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtrac
switch (status)
{
case eConnectionStatusTimedOut:
+ case eConnectionStatusInterrupted:
timed_out = true;
break;
case eConnectionStatusSuccess:
@@ -457,7 +465,8 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
assert (content_length <= m_bytes.size());
assert (total_length <= m_bytes.size());
assert (content_length <= total_length);
-
+ const size_t content_end = content_start + content_length;
+
bool success = true;
std::string &packet_str = packet.GetStringRef();
@@ -471,7 +480,45 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
if (!m_history.DidDumpToLog ())
m_history.Dump (log);
- log->Printf("<%4" PRIu64 "> read packet: %.*s", (uint64_t)total_length, (int)(total_length), m_bytes.c_str());
+ bool binary = false;
+ // Only detect binary for packets that start with a '$' and have a '#CC' checksum
+ if (m_bytes[0] == '$' && total_length > 4)
+ {
+ for (size_t i=0; !binary && i<total_length; ++i)
+ {
+ if (isprint(m_bytes[i]) == 0)
+ binary = true;
+ }
+ }
+ if (binary)
+ {
+ StreamString strm;
+ // Packet header...
+ strm.Printf("<%4" PRIu64 "> read packet: %c", (uint64_t)total_length, m_bytes[0]);
+ for (size_t i=content_start; i<content_end; ++i)
+ {
+ // Remove binary escaped bytes when displaying the packet...
+ const char ch = m_bytes[i];
+ if (ch == 0x7d)
+ {
+ // 0x7d is the escape character. The next character is to
+ // be XOR'd with 0x20.
+ const char escapee = m_bytes[++i] ^ 0x20;
+ strm.Printf("%2.2x", escapee);
+ }
+ else
+ {
+ strm.Printf("%2.2x", (uint8_t)ch);
+ }
+ }
+ // Packet footer...
+ strm.Printf("%c%c%c", m_bytes[total_length-3], m_bytes[total_length-2], m_bytes[total_length-1]);
+ log->PutCString(strm.GetString().c_str());
+ }
+ else
+ {
+ log->Printf("<%4" PRIu64 "> read packet: %.*s", (uint64_t)total_length, (int)(total_length), m_bytes.c_str());
+ }
}
m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length);
@@ -482,7 +529,7 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
// run-length encoding in the process.
// Reserve enough byte for the most common case (no RLE used)
packet_str.reserve(m_bytes.length());
- for (std::string::const_iterator c = m_bytes.begin() + content_start; c != m_bytes.begin() + content_start + content_length; ++c)
+ for (std::string::const_iterator c = m_bytes.begin() + content_start; c != m_bytes.begin() + content_end; ++c)
{
if (*c == '*')
{
@@ -610,6 +657,10 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
lldb_private::ProcessLaunchInfo &launch_info,
uint16_t &out_port)
{
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf ("GDBRemoteCommunication::%s(hostname=%s, in_port=%" PRIu16 ", out_port=%" PRIu16, __FUNCTION__, hostname ? hostname : "<empty>", in_port, out_port);
+
out_port = in_port;
Error error;
// If we locate debugserver, keep that located version around
@@ -622,24 +673,34 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
// to the debugserver to use and use it if we do.
const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
if (env_debugserver_path)
+ {
debugserver_file_spec.SetFile (env_debugserver_path, false);
+ if (log)
+ log->Printf ("GDBRemoteCommunication::%s() gdb-remote stub exe path set from environment variable: %s", __FUNCTION__, env_debugserver_path);
+ }
else
debugserver_file_spec = g_debugserver_file_spec;
bool debugserver_exists = debugserver_file_spec.Exists();
if (!debugserver_exists)
{
// The debugserver binary is in the LLDB.framework/Resources
- // directory.
- if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
+ // directory.
+ if (HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir, debugserver_file_spec))
{
- debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
+ debugserver_file_spec.AppendPathComponent (DEBUGSERVER_BASENAME);
debugserver_exists = debugserver_file_spec.Exists();
if (debugserver_exists)
{
+ if (log)
+ log->Printf ("GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());
+
g_debugserver_file_spec = debugserver_file_spec;
}
else
{
+ if (log)
+ log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());
+
g_debugserver_file_spec.Clear();
debugserver_file_spec.Clear();
}
@@ -690,9 +751,9 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
// Binding to port zero, we need to figure out what port it ends up
// using using a named pipe...
FileSpec tmpdir_file_spec;
- if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
{
- tmpdir_file_spec.GetFilename().SetCString("debugserver-named-pipe.XXXXXX");
+ tmpdir_file_spec.AppendPathComponent("debugserver-named-pipe.XXXXXX");
strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path));
}
else
@@ -702,7 +763,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
if (::mktemp (named_pipe_path))
{
-#if defined(_MSC_VER)
+#if defined(_WIN32)
if ( false )
#else
if (::mkfifo(named_pipe_path, 0600) == 0)
@@ -722,21 +783,28 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
{
// No host and port given, so lets listen on our end and make the debugserver
// connect to us..
- error = StartListenThread ("localhost", 0);
+ error = StartListenThread ("127.0.0.1", 0);
if (error.Fail())
return error;
ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
- out_port = connection->GetBoundPort(3);
- assert (out_port != 0);
- char port_cstr[32];
- snprintf(port_cstr, sizeof(port_cstr), "localhost:%i", out_port);
- // Send the host and port down that debugserver and specify an option
- // so that it connects back to the port we are listening to in this process
- debugserver_args.AppendArgument("--reverse-connect");
- debugserver_args.AppendArgument(port_cstr);
+ // Wait for 10 seconds to resolve the bound port
+ out_port = connection->GetListeningPort(10);
+ if (out_port > 0)
+ {
+ char port_cstr[32];
+ snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", out_port);
+ // Send the host and port down that debugserver and specify an option
+ // so that it connects back to the port we are listening to in this process
+ debugserver_args.AppendArgument("--reverse-connect");
+ debugserver_args.AppendArgument(port_cstr);
+ }
+ else
+ {
+ error.SetErrorString ("failed to bind to port 0 on 127.0.0.1");
+ return error;
+ }
}
-
const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
if (env_debugserver_log_file)
@@ -751,7 +819,25 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
debugserver_args.AppendArgument(arg_cstr);
}
-
+
+ // Add additional args, starting with LLDB_DEBUGSERVER_EXTRA_ARG_1 until an env var doesn't come back.
+ uint32_t env_var_index = 1;
+ bool has_env_var;
+ do
+ {
+ char env_var_name[64];
+ snprintf (env_var_name, sizeof (env_var_name), "LLDB_DEBUGSERVER_EXTRA_ARG_%" PRIu32, env_var_index++);
+ const char *extra_arg = getenv(env_var_name);
+ has_env_var = extra_arg != nullptr;
+
+ if (has_env_var)
+ {
+ debugserver_args.AppendArgument (extra_arg);
+ if (log)
+ log->Printf ("GDBRemoteCommunication::%s adding env var %s contents to stub command line (%s)", __FUNCTION__, env_var_name, extra_arg);
+ }
+ } while (has_env_var);
+
// Close STDIN, STDOUT and STDERR. We might need to redirect them
// to "/dev/null" if we run into any problems.
launch_info.AppendCloseFileAction (STDIN_FILENO);
@@ -760,31 +846,34 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
error = Host::LaunchProcess(launch_info);
- if (named_pipe_path[0])
+ if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
{
- File name_pipe_file;
- error = name_pipe_file.Open(named_pipe_path, File::eOpenOptionRead);
- if (error.Success())
+ if (named_pipe_path[0])
{
- 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();
+ File name_pipe_file;
+ error = name_pipe_file.Open(named_pipe_path, File::eOpenOptionRead);
+ 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();
+ }
+ FileSystem::Unlink(named_pipe_path);
+ }
+ else if (listen)
+ {
+
+ }
+ else
+ {
+ // Make sure we actually connect with the debugserver...
+ JoinListenThread();
}
- Host::Unlink(named_pipe_path);
- }
- else if (listen)
- {
-
- }
- else
- {
- // Make sure we actually connect with the debugserver...
- JoinListenThread();
}
}
else
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index d8361113ddc8..b11d38563207 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -271,7 +271,7 @@ protected:
lldb_private::Error
- StartListenThread (const char *hostname = "localhost",
+ StartListenThread (const char *hostname = "127.0.0.1",
uint16_t port = 0);
bool
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index ab3bf7f5aa2a..5e4ed7648f95 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -17,6 +17,7 @@
#include <sstream>
// Other libraries and framework includes
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Core/ConnectionFileDescriptor.h"
@@ -26,7 +27,9 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Host/TimeValue.h"
+#include "lldb/Target/Target.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
@@ -37,7 +40,7 @@
using namespace lldb;
using namespace lldb_private;
-#ifdef LLDB_DISABLE_POSIX
+#if defined(LLDB_DISABLE_POSIX) && !defined(SIGSTOP)
#define SIGSTOP 17
#endif
@@ -56,7 +59,9 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_supports_vCont_s (eLazyBoolCalculate),
m_supports_vCont_S (eLazyBoolCalculate),
m_qHostInfo_is_valid (eLazyBoolCalculate),
+ m_curr_pid_is_valid (eLazyBoolCalculate),
m_qProcessInfo_is_valid (eLazyBoolCalculate),
+ m_qGDBServerVersion_is_valid (eLazyBoolCalculate),
m_supports_alloc_dealloc_memory (eLazyBoolCalculate),
m_supports_memory_region_info (eLazyBoolCalculate),
m_supports_watchpoint_support_info (eLazyBoolCalculate),
@@ -65,10 +70,14 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_attach_or_wait_reply(eLazyBoolCalculate),
m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
m_supports_p (eLazyBoolCalculate),
+ m_supports_x (eLazyBoolCalculate),
+ m_avoid_g_packets (eLazyBoolCalculate),
m_supports_QSaveRegisterState (eLazyBoolCalculate),
+ m_supports_qXfer_auxv_read (eLazyBoolCalculate),
m_supports_qXfer_libraries_read (eLazyBoolCalculate),
m_supports_qXfer_libraries_svr4_read (eLazyBoolCalculate),
m_supports_augmented_libraries_svr4_read (eLazyBoolCalculate),
+ m_supports_jThreadExtendedInfo (eLazyBoolCalculate),
m_supports_qProcessInfoPID (true),
m_supports_qfProcessInfo (true),
m_supports_qUserName (true),
@@ -81,6 +90,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_supports_z4 (true),
m_supports_QEnvironment (true),
m_supports_QEnvironmentHexEncoded (true),
+ m_curr_pid (LLDB_INVALID_PROCESS_ID),
m_curr_tid (LLDB_INVALID_THREAD_ID),
m_curr_tid_run (LLDB_INVALID_THREAD_ID),
m_num_supported_hardware_watchpoints (0),
@@ -90,6 +100,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_async_result (PacketResult::Success),
m_async_response (),
m_async_signal (-1),
+ m_interrupt_sent (false),
m_thread_id_to_used_usec_map (),
m_host_arch(),
m_process_arch(),
@@ -99,6 +110,8 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_os_build (),
m_os_kernel (),
m_hostname (),
+ m_gdb_server_name(),
+ m_gdb_server_version(UINT32_MAX),
m_default_packet_timeout (0),
m_max_packet_size (0)
{
@@ -187,6 +200,16 @@ GDBRemoteCommunicationClient::GetQXferLibrariesReadSupported ()
return (m_supports_qXfer_libraries_read == eLazyBoolYes);
}
+bool
+GDBRemoteCommunicationClient::GetQXferAuxvReadSupported ()
+{
+ if (m_supports_qXfer_auxv_read == eLazyBoolCalculate)
+ {
+ GetRemoteQSupported();
+ }
+ return (m_supports_qXfer_auxv_read == eLazyBoolYes);
+}
+
uint64_t
GDBRemoteCommunicationClient::GetRemoteMaxPacketSize()
{
@@ -205,8 +228,18 @@ GDBRemoteCommunicationClient::QueryNoAckModeSupported ()
m_send_acks = true;
m_supports_not_sending_acks = eLazyBoolNo;
+ // This is the first real packet that we'll send in a debug session and it may take a little
+ // longer than normal to receive a reply. Wait at least 6 seconds for a reply to this packet.
+
+ const uint32_t minimum_timeout = 6;
+ uint32_t old_timeout = GetPacketTimeoutInMicroSeconds() / lldb_private::TimeValue::MicroSecPerSec;
+ SetPacketTimeout (std::max (old_timeout, minimum_timeout));
+
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) == PacketResult::Success)
+ PacketResult packet_send_result = SendPacketAndWaitForResponse("QStartNoAckMode", response, false);
+ SetPacketTimeout (old_timeout);
+
+ if (packet_send_result == PacketResult::Success)
{
if (response.IsOKResponse())
{
@@ -287,13 +320,18 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_vCont_s = eLazyBoolCalculate;
m_supports_vCont_S = eLazyBoolCalculate;
m_supports_p = eLazyBoolCalculate;
+ m_supports_x = eLazyBoolCalculate;
m_supports_QSaveRegisterState = eLazyBoolCalculate;
m_qHostInfo_is_valid = eLazyBoolCalculate;
+ m_curr_pid_is_valid = eLazyBoolCalculate;
m_qProcessInfo_is_valid = eLazyBoolCalculate;
+ m_qGDBServerVersion_is_valid = eLazyBoolCalculate;
m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
m_supports_memory_region_info = eLazyBoolCalculate;
m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
m_attach_or_wait_reply = eLazyBoolCalculate;
+ m_avoid_g_packets = eLazyBoolCalculate;
+ m_supports_qXfer_auxv_read = eLazyBoolCalculate;
m_supports_qXfer_libraries_read = eLazyBoolCalculate;
m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
@@ -310,8 +348,18 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_z4 = true;
m_supports_QEnvironment = true;
m_supports_QEnvironmentHexEncoded = true;
+
m_host_arch.Clear();
m_process_arch.Clear();
+ m_os_version_major = UINT32_MAX;
+ m_os_version_minor = UINT32_MAX;
+ m_os_version_update = UINT32_MAX;
+ m_os_build.clear();
+ m_os_kernel.clear();
+ m_hostname.clear();
+ m_gdb_server_name.clear();
+ m_gdb_server_version = UINT32_MAX;
+ m_default_packet_timeout = 0;
m_max_packet_size = 0;
}
@@ -320,8 +368,9 @@ void
GDBRemoteCommunicationClient::GetRemoteQSupported ()
{
// Clear out any capabilities we expect to see in the qSupported response
- m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
+ m_supports_qXfer_auxv_read = eLazyBoolNo;
m_supports_qXfer_libraries_read = eLazyBoolNo;
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if not, we assume no limit
@@ -331,6 +380,8 @@ GDBRemoteCommunicationClient::GetRemoteQSupported ()
/*send_async=*/false) == PacketResult::Success)
{
const char *response_cstr = response.GetStringRef().c_str();
+ if (::strstr (response_cstr, "qXfer:auxv:read+"))
+ m_supports_qXfer_auxv_read = eLazyBoolYes;
if (::strstr (response_cstr, "qXfer:libraries-svr4:read+"))
m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
if (::strstr (response_cstr, "augmented-libraries-svr4-read"))
@@ -457,6 +508,42 @@ GDBRemoteCommunicationClient::GetpPacketSupported (lldb::tid_t tid)
return m_supports_p;
}
+bool
+GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported ()
+{
+ if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate)
+ {
+ StringExtractorGDBRemote response;
+ m_supports_jThreadExtendedInfo = eLazyBoolNo;
+ if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response, false) == PacketResult::Success)
+ {
+ if (response.IsOKResponse())
+ {
+ m_supports_jThreadExtendedInfo = eLazyBoolYes;
+ }
+ }
+ }
+ return m_supports_jThreadExtendedInfo;
+}
+
+bool
+GDBRemoteCommunicationClient::GetxPacketSupported ()
+{
+ if (m_supports_x == eLazyBoolCalculate)
+ {
+ StringExtractorGDBRemote response;
+ m_supports_x = eLazyBoolNo;
+ char packet[256];
+ snprintf (packet, sizeof (packet), "x0,0");
+ if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success)
+ {
+ if (response.IsOKResponse())
+ m_supports_x = eLazyBoolYes;
+ }
+ }
+ return m_supports_x;
+}
+
GDBRemoteCommunicationClient::PacketResult
GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses
(
@@ -502,11 +589,8 @@ GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses
{
return PacketResult::ErrorReplyInvalid;
}
- // Skip past m or l
- const char *s = this_string.c_str() + 1;
-
- // Concatenate the result so far
- response_string += s;
+ // Concatenate the result so far (skipping 'm' or 'l')
+ response_string.append(this_string, 1, std::string::npos);
if (first_char == 'l')
// We're done
return PacketResult::Success;
@@ -550,7 +634,6 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
PacketResult packet_result = PacketResult::ErrorSendFailed;
Mutex::Locker locker;
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- size_t response_len = 0;
if (GetSequenceMutex (locker))
{
packet_result = SendPacketAndWaitForResponseNoLock (payload, payload_length, response);
@@ -588,7 +671,6 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
// Swap the response buffer to avoid malloc and string copy
response.GetStringRef().swap (m_async_response.GetStringRef());
- response_len = response.GetStringRef().size();
packet_result = m_async_result;
}
else
@@ -772,6 +854,8 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
log->Printf ("GDBRemoteCommunicationClient::%s () sending continue packet: %s", __FUNCTION__, continue_packet.c_str());
if (SendPacketNoLock(continue_packet.c_str(), continue_packet.size()) != PacketResult::Success)
state = eStateInvalid;
+ else
+ m_interrupt_sent = false;
m_private_is_running.SetValue (true, eBroadcastAlways);
}
@@ -1047,7 +1131,7 @@ GDBRemoteCommunicationClient::SendAsyncSignal (int signo)
// then the caller that requested the interrupt will want to keep the sequence
// locked down so that no one else can send packets while the caller has control.
// This function usually gets called when we are running and need to stop the
-// target. It can also be used when we are running and and we need to do something
+// target. It can also be used when we are running and we need to do something
// else (like read/write memory), so we need to interrupt the running process
// (gdb remote protocol requires this), and do what we need to do, then resume.
@@ -1128,13 +1212,40 @@ GDBRemoteCommunicationClient::SendInterrupt
lldb::pid_t
GDBRemoteCommunicationClient::GetCurrentProcessID ()
{
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, false) == PacketResult::Success)
+ if (m_curr_pid_is_valid == eLazyBoolYes)
+ return m_curr_pid;
+
+ // First try to retrieve the pid via the qProcessInfo request.
+ GetCurrentProcessInfo ();
+ if (m_curr_pid_is_valid == eLazyBoolYes)
+ {
+ // We really got it.
+ return m_curr_pid;
+ }
+ else
{
- if (response.GetChar() == 'Q')
- if (response.GetChar() == 'C')
- return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
+ // If we don't get a response for qProcessInfo, check if $qC gives us a result.
+ // $qC only returns a real process id on older debugserver and lldb-platform stubs.
+ // The gdb remote protocol documents $qC as returning the thread id, which newer
+ // debugserver and lldb-gdbserver stubs return correctly.
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, false) == PacketResult::Success)
+ {
+ if (response.GetChar() == 'Q')
+ {
+ if (response.GetChar() == 'C')
+ {
+ m_curr_pid = response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
+ if (m_curr_pid != LLDB_INVALID_PROCESS_ID)
+ {
+ m_curr_pid_is_valid = eLazyBoolYes;
+ return m_curr_pid;
+ }
+ }
+ }
+ }
}
+
return LLDB_INVALID_PROCESS_ID;
}
@@ -1168,7 +1279,7 @@ int
GDBRemoteCommunicationClient::SendArgumentsPacket (const ProcessLaunchInfo &launch_info)
{
// Since we don't get the send argv0 separate from the executable path, we need to
- // make sure to use the actual exectuable path found in the launch_info...
+ // make sure to use the actual executable path found in the launch_info...
std::vector<const char *> argv;
FileSpec exe_file = launch_info.GetExecutableFile();
std::string exe_path;
@@ -1304,6 +1415,41 @@ GDBRemoteCommunicationClient::SendLaunchArchPacket (char const *arch)
return -1;
}
+int
+GDBRemoteCommunicationClient::SendLaunchEventDataPacket (char const *data, bool *was_supported)
+{
+ if (data && *data != '\0')
+ {
+ StreamString packet;
+ packet.Printf("QSetProcessEvent:%s", data);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
+ {
+ if (response.IsOKResponse())
+ {
+ if (was_supported)
+ *was_supported = true;
+ return 0;
+ }
+ else if (response.IsUnsupportedResponse())
+ {
+ if (was_supported)
+ *was_supported = false;
+ return -1;
+ }
+ else
+ {
+ uint8_t error = response.GetError();
+ if (was_supported)
+ *was_supported = true;
+ if (error)
+ return error;
+ }
+ }
+ }
+ return -1;
+}
+
bool
GDBRemoteCommunicationClient::GetOSVersion (uint32_t &major,
uint32_t &minor,
@@ -1384,10 +1530,75 @@ GDBRemoteCommunicationClient::GetProcessArchitecture ()
return m_process_arch;
}
+bool
+GDBRemoteCommunicationClient::GetGDBServerVersion()
+{
+ if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate)
+ {
+ m_gdb_server_name.clear();
+ m_gdb_server_version = 0;
+ m_qGDBServerVersion_is_valid = eLazyBoolNo;
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse ("qGDBServerVersion", response, false) == PacketResult::Success)
+ {
+ if (response.IsNormalResponse())
+ {
+ std::string name;
+ std::string value;
+ bool success = false;
+ while (response.GetNameColonValue(name, value))
+ {
+ if (name.compare("name") == 0)
+ {
+ success = true;
+ m_gdb_server_name.swap(value);
+ }
+ else if (name.compare("version") == 0)
+ {
+ size_t dot_pos = value.find('.');
+ if (dot_pos != std::string::npos)
+ value[dot_pos] = '\0';
+ const uint32_t version = Args::StringToUInt32(value.c_str(), UINT32_MAX, 0);
+ if (version != UINT32_MAX)
+ {
+ success = true;
+ m_gdb_server_version = version;
+ }
+ }
+ }
+ if (success)
+ m_qGDBServerVersion_is_valid = eLazyBoolYes;
+ }
+ }
+ }
+ return m_qGDBServerVersion_is_valid == eLazyBoolYes;
+}
+
+const char *
+GDBRemoteCommunicationClient::GetGDBServerProgramName()
+{
+ if (GetGDBServerVersion())
+ {
+ if (!m_gdb_server_name.empty())
+ return m_gdb_server_name.c_str();
+ }
+ return NULL;
+}
+
+uint32_t
+GDBRemoteCommunicationClient::GetGDBServerProgramVersion()
+{
+ if (GetGDBServerVersion())
+ return m_gdb_server_version;
+ return 0;
+}
bool
GDBRemoteCommunicationClient::GetHostInfo (bool force)
{
+ Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS));
+
if (force || m_qHostInfo_is_valid == eLazyBoolCalculate)
{
m_qHostInfo_is_valid = eLazyBoolNo;
@@ -1432,10 +1643,7 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
}
else if (name.compare("triple") == 0)
{
- // The triple comes as ASCII hex bytes since it contains '-' chars
- extractor.GetStringRef().swap(value);
- extractor.SetFilePos(0);
- extractor.GetHexByteString (triple);
+ triple.swap(value);
++num_keys_decoded;
}
else if (name.compare ("distribution_id") == 0)
@@ -1548,6 +1756,7 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
{
switch (m_host_arch.GetMachine())
{
+ case llvm::Triple::aarch64:
case llvm::Triple::arm:
case llvm::Triple::thumb:
os_name = "ios";
@@ -1588,6 +1797,7 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
{
switch (m_host_arch.GetMachine())
{
+ case llvm::Triple::aarch64:
case llvm::Triple::arm:
case llvm::Triple::thumb:
host_triple.setOS(llvm::Triple::IOS);
@@ -1619,6 +1829,9 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
{
assert (byte_order == m_host_arch.GetByteOrder());
}
+
+ if (log)
+ log->Printf ("GDBRemoteCommunicationClient::%s parsed host architecture as %s, triple as %s from triple text %s", __FUNCTION__, m_host_arch.GetArchitectureName () ? m_host_arch.GetArchitectureName () : "<null-arch-name>", m_host_arch.GetTriple ().getTriple ().c_str(), triple.c_str ());
}
if (!distribution_id.empty ())
m_host_arch.SetDistributionId (distribution_id.c_str ());
@@ -1682,7 +1895,9 @@ GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions)
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
{
- if (!response.IsErrorResponse())
+ if (response.IsUnsupportedResponse())
+ m_supports_alloc_dealloc_memory = eLazyBoolNo;
+ else if (!response.IsErrorResponse())
return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
}
else
@@ -1705,7 +1920,9 @@ GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr)
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
{
- if (response.IsOKResponse())
+ if (response.IsUnsupportedResponse())
+ m_supports_alloc_dealloc_memory = eLazyBoolNo;
+ else if (response.IsOKResponse())
return true;
}
else
@@ -1746,14 +1963,16 @@ GDBRemoteCommunicationClient::Detach (bool keep_stopped)
}
else
{
- PacketResult packet_result = SendPacket ("D1", 2);
+ StringExtractorGDBRemote response;
+ PacketResult packet_result = SendPacketAndWaitForResponse ("D1", 1, response, false);
if (packet_result != PacketResult::Success)
error.SetErrorString ("Sending extended disconnect packet failed.");
}
}
else
{
- PacketResult packet_result = SendPacket ("D", 1);
+ StringExtractorGDBRemote response;
+ PacketResult packet_result = SendPacketAndWaitForResponse ("D", 1, response, false);
if (packet_result != PacketResult::Success)
error.SetErrorString ("Sending disconnect packet failed.");
}
@@ -2051,6 +2270,25 @@ GDBRemoteCommunicationClient::SetDisableASLR (bool enable)
return -1;
}
+int
+GDBRemoteCommunicationClient::SetDetachOnError (bool enable)
+{
+ char packet[32];
+ const int packet_len = ::snprintf (packet, sizeof (packet), "QSetDetachOnError:%i", enable ? 1 : 0);
+ assert (packet_len < (int)sizeof(packet));
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
+ {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
+ }
+ return -1;
+}
+
+
bool
GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info)
{
@@ -2093,10 +2331,6 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot
}
else if (name.compare("triple") == 0)
{
- // The triple comes as ASCII hex bytes since it contains '-' chars
- extractor.GetStringRef().swap(value);
- extractor.SetFilePos(0);
- extractor.GetHexByteString (value);
process_info.GetArchitecture ().SetTriple (value.c_str());
}
else if (name.compare("name") == 0)
@@ -2192,8 +2426,8 @@ 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))
{
if (name.compare("cputype") == 0)
@@ -2208,6 +2442,11 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo ()
if (sub != 0)
++num_keys_decoded;
}
+ else if (name.compare("triple") == 0)
+ {
+ triple = value;
+ ++num_keys_decoded;
+ }
else if (name.compare("ostype") == 0)
{
os_name.swap (value);
@@ -2220,15 +2459,10 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo ()
}
else if (name.compare("endian") == 0)
{
- ++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;
+ if (value.compare("little") == 0 ||
+ value.compare("big") == 0 ||
+ value.compare("pdp") == 0)
+ ++num_keys_decoded;
}
else if (name.compare("ptrsize") == 0)
{
@@ -2236,20 +2470,42 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo ()
if (pointer_byte_size != 0)
++num_keys_decoded;
}
+ else if (name.compare("pid") == 0)
+ {
+ pid = Args::StringToUInt64(value.c_str(), 0, 16);
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ ++num_keys_decoded;
+ }
}
if (num_keys_decoded > 0)
m_qProcessInfo_is_valid = eLazyBoolYes;
- if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty())
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ {
+ m_curr_pid_is_valid = eLazyBoolYes;
+ m_curr_pid = pid;
+ }
+
+ // Set the ArchSpec from the triple if we have it.
+ if (!triple.empty ())
+ {
+ m_process_arch.SetTriple (triple.c_str ());
+ if (pointer_byte_size)
+ {
+ assert (pointer_byte_size == m_process_arch.GetAddressByteSize());
+ }
+ }
+ else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty())
{
m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
if (pointer_byte_size)
{
assert (pointer_byte_size == m_process_arch.GetAddressByteSize());
}
+ 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));
- return true;
}
+ return true;
}
}
else
@@ -2333,7 +2589,7 @@ GDBRemoteCommunicationClient::FindProcesses (const ProcessInstanceInfoMatch &mat
const ArchSpec &match_arch = match_info.GetProcessInfo().GetArchitecture();
const llvm::Triple &triple = match_arch.GetTriple();
packet.PutCString("triple:");
- packet.PutCStringAsRawHex8(triple.getTriple().c_str());
+ packet.PutCString(triple.getTriple().c_str());
packet.PutChar (';');
}
}
@@ -2429,8 +2685,8 @@ GDBRemoteCommunicationClient::TestPacketSpeed (const uint32_t num_packets)
{
static uint32_t g_send_sizes[] = { 0, 64, 128, 512, 1024 };
static uint32_t g_recv_sizes[] = { 0, 64, 128, 512, 1024 }; //, 4*1024, 8*1024, 16*1024, 32*1024, 48*1024, 64*1024, 96*1024, 128*1024 };
- const size_t k_num_send_sizes = sizeof(g_send_sizes)/sizeof(uint32_t);
- const size_t k_num_recv_sizes = sizeof(g_recv_sizes)/sizeof(uint32_t);
+ const size_t k_num_send_sizes = llvm::array_lengthof(g_send_sizes);
+ const size_t k_num_recv_sizes = llvm::array_lengthof(g_recv_sizes);
const uint64_t k_recv_amount = 4*1024*1024; // Receive 4MB
for (uint32_t send_idx = 0; send_idx < k_num_send_sizes; ++send_idx)
{
@@ -2539,7 +2795,7 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const
hostname = remote_accept_hostname;
else
{
- if (Host::GetHostname (hostname))
+ if (HostInfo::GetHostname(hostname))
{
// Make the GDB server we launch only accept connections from this host
stream.Printf("host:%s;", hostname.c_str());
@@ -2687,7 +2943,7 @@ GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type,
type,
addr,
length);
- // Check we havent overwritten the end of the packet buffer
+ // Check we haven't overwritten the end of the packet buffer
assert (packet_len + 1 < (int)sizeof(packet));
StringExtractorGDBRemote response;
// Try to send the breakpoint packet, and check that it was correctly sent
@@ -2715,7 +2971,7 @@ GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type,
}
}
}
- // Signal generic faliure
+ // Signal generic failure
return UINT8_MAX;
}
@@ -2977,7 +3233,7 @@ GDBRemoteCommunicationClient::GetFilePermissions(const char *path, uint32_t &fil
else
{
const uint32_t mode = response.GetS32(-1);
- if (mode == -1)
+ if (static_cast<int32_t>(mode) == -1)
{
if (response.GetChar() == ',')
{
@@ -3217,6 +3473,38 @@ GDBRemoteCommunicationClient::CalculateMD5 (const lldb_private::FileSpec& file_s
}
bool
+GDBRemoteCommunicationClient::AvoidGPackets (ProcessGDBRemote *process)
+{
+ // Some targets have issues with g/G packets and we need to avoid using them
+ if (m_avoid_g_packets == eLazyBoolCalculate)
+ {
+ if (process)
+ {
+ m_avoid_g_packets = eLazyBoolNo;
+ const ArchSpec &arch = process->GetTarget().GetArchitecture();
+ if (arch.IsValid()
+ && arch.GetTriple().getVendor() == llvm::Triple::Apple
+ && arch.GetTriple().getOS() == llvm::Triple::IOS
+ && arch.GetTriple().getArch() == llvm::Triple::aarch64)
+ {
+ m_avoid_g_packets = eLazyBoolYes;
+ uint32_t gdb_server_version = GetGDBServerProgramVersion();
+ if (gdb_server_version != 0)
+ {
+ const char *gdb_server_name = GetGDBServerProgramName();
+ if (gdb_server_name && strcmp(gdb_server_name, "debugserver") == 0)
+ {
+ if (gdb_server_version >= 310)
+ m_avoid_g_packets = eLazyBoolNo;
+ }
+ }
+ }
+ }
+ }
+ return m_avoid_g_packets == eLazyBoolYes;
+}
+
+bool
GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, uint32_t reg, StringExtractorGDBRemote &response)
{
Mutex::Locker locker;
@@ -3309,7 +3597,7 @@ GDBRemoteCommunicationClient::SaveRegisterState (lldb::tid_t tid, uint32_t &save
bool
GDBRemoteCommunicationClient::RestoreRegisterState (lldb::tid_t tid, uint32_t save_id)
{
- // We use the "m_supports_QSaveRegisterState" variable here becuase the
+ // We use the "m_supports_QSaveRegisterState" variable here because the
// QSaveRegisterState and QRestoreRegisterState packets must both be supported in
// order to be useful
if (m_supports_QSaveRegisterState == eLazyBoolNo)
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index a1e982b3ec4e..fddcd6cd1426 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -92,7 +92,7 @@ public:
// indicates if the packet was send and any response was received
// even in the response is UNIMPLEMENTED. If the packet failed to
// get a response, then false is returned. This quickly tells us
- // if we were able to connect and communicte with the remote GDB
+ // if we were able to connect and communicate with the remote GDB
// server
bool
QueryNoAckModeSupported ();
@@ -159,6 +159,10 @@ public:
int
SendLaunchArchPacket (const char *arch);
+
+ int
+ SendLaunchEventDataPacket (const char *data, bool *was_supported = NULL);
+
//------------------------------------------------------------------
/// Sends a "vAttach:PID" where PID is in hex.
///
@@ -201,13 +205,25 @@ public:
/// be launched with the 'A' packet.
///
/// @param[in] enable
- /// A boolean value indicating wether to disable ASLR or not.
+ /// A boolean value indicating whether to disable ASLR or not.
///
/// @return
/// Zero if the for success, or an error code for failure.
//------------------------------------------------------------------
int
SetDisableASLR (bool enable);
+
+ //------------------------------------------------------------------
+ /// Sets the DetachOnError flag to \a enable for the process controlled by the stub.
+ ///
+ /// @param[in] enable
+ /// A boolean value indicating whether to detach on error or not.
+ ///
+ /// @return
+ /// Zero if the for success, or an error code for failure.
+ //------------------------------------------------------------------
+ int
+ SetDetachOnError (bool enable);
//------------------------------------------------------------------
/// Sets the working directory to \a path for a process that will
@@ -217,7 +233,7 @@ public:
/// directory for the platform process.
///
/// @param[in] path
- /// The path to a directory to use when launching our processs
+ /// The path to a directory to use when launching our process
///
/// @return
/// Zero if the for success, or an error code for failure.
@@ -279,6 +295,9 @@ public:
GetpPacketSupported (lldb::tid_t tid);
bool
+ GetxPacketSupported ();
+
+ bool
GetVAttachOrWaitSupported ();
bool
@@ -384,6 +403,9 @@ public:
SetCurrentThreadForRun (uint64_t tid);
bool
+ GetQXferAuxvReadSupported ();
+
+ bool
GetQXferLibrariesReadSupported ();
bool
@@ -491,7 +513,19 @@ public:
bool
RestoreRegisterState (lldb::tid_t tid, uint32_t save_id);
+
+ const char *
+ GetGDBServerProgramName();
+ uint32_t
+ GetGDBServerProgramVersion();
+
+ bool
+ AvoidGPackets(ProcessGDBRemote *process);
+
+ bool
+ GetThreadExtendedInfoSupported();
+
protected:
PacketResult
@@ -502,6 +536,9 @@ protected:
bool
GetCurrentProcessInfo ();
+ bool
+ GetGDBServerVersion();
+
//------------------------------------------------------------------
// Classes that inherit from GDBRemoteCommunicationClient can see and modify these
//------------------------------------------------------------------
@@ -515,7 +552,9 @@ protected:
lldb_private::LazyBool m_supports_vCont_s;
lldb_private::LazyBool m_supports_vCont_S;
lldb_private::LazyBool m_qHostInfo_is_valid;
+ lldb_private::LazyBool m_curr_pid_is_valid;
lldb_private::LazyBool m_qProcessInfo_is_valid;
+ lldb_private::LazyBool m_qGDBServerVersion_is_valid;
lldb_private::LazyBool m_supports_alloc_dealloc_memory;
lldb_private::LazyBool m_supports_memory_region_info;
lldb_private::LazyBool m_supports_watchpoint_support_info;
@@ -524,10 +563,14 @@ protected:
lldb_private::LazyBool m_attach_or_wait_reply;
lldb_private::LazyBool m_prepare_for_reg_writing_reply;
lldb_private::LazyBool m_supports_p;
+ lldb_private::LazyBool m_supports_x;
+ lldb_private::LazyBool m_avoid_g_packets;
lldb_private::LazyBool m_supports_QSaveRegisterState;
+ lldb_private::LazyBool m_supports_qXfer_auxv_read;
lldb_private::LazyBool m_supports_qXfer_libraries_read;
lldb_private::LazyBool m_supports_qXfer_libraries_svr4_read;
lldb_private::LazyBool m_supports_augmented_libraries_svr4_read;
+ lldb_private::LazyBool m_supports_jThreadExtendedInfo;
bool
m_supports_qProcessInfoPID:1,
@@ -543,7 +586,7 @@ protected:
m_supports_QEnvironment:1,
m_supports_QEnvironmentHexEncoded:1;
-
+ lldb::pid_t m_curr_pid;
lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations
lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for continue, step, etc
@@ -570,6 +613,8 @@ protected:
std::string m_os_build;
std::string m_os_kernel;
std::string m_hostname;
+ std::string m_gdb_server_name; // from reply to qGDBServerVersion, empty if qGDBServerVersion is not supported
+ uint32_t m_gdb_server_version; // from reply to qGDBServerVersion, zero if qGDBServerVersion is not supported
uint32_t m_default_packet_timeout;
uint64_t m_max_packet_size; // as returned by qSupported
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index df95542d2c0f..ffcdd169eb9f 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -9,24 +9,38 @@
#include <errno.h>
+#include "lldb/Host/Config.h"
+
#include "GDBRemoteCommunicationServer.h"
#include "lldb/Core/StreamGDBRemote.h"
// C Includes
// C++ Includes
+#include <cstring>
+#include <chrono>
+#include <thread>
+
// 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/Debug.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/File.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Host/TimeValue.h"
+#include "lldb/Target/FileAction.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
+#include "lldb/Target/NativeRegisterContext.h"
+#include "Host/common/NativeProcessProtocol.h"
+#include "Host/common/NativeThreadProtocol.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
@@ -37,6 +51,22 @@ using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
+// GDBRemote Errors
+//----------------------------------------------------------------------
+
+namespace
+{
+ enum GDBRemoteServerError
+ {
+ // Set to the first unused error number in literal form below
+ eErrorFirst = 29,
+ eErrorNoProcess = eErrorFirst,
+ eErrorResume,
+ eErrorExitStatus
+ };
+}
+
+//----------------------------------------------------------------------
// GDBRemoteCommunicationServer constructor
//----------------------------------------------------------------------
GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
@@ -50,12 +80,28 @@ GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
m_proc_infos (),
m_proc_infos_index (0),
m_port_map (),
- m_port_offset(0)
+ m_port_offset(0),
+ m_current_tid (LLDB_INVALID_THREAD_ID),
+ m_continue_tid (LLDB_INVALID_THREAD_ID),
+ m_debugged_process_mutex (Mutex::eMutexTypeRecursive),
+ m_debugged_process_sp (),
+ m_debugger_sp (),
+ m_stdio_communication ("process.stdio"),
+ m_exit_now (false),
+ m_inferior_prev_state (StateType::eStateInvalid),
+ m_thread_suffix_supported (false),
+ m_list_threads_in_stop_reply (false),
+ m_active_auxv_buffer_sp (),
+ m_saved_registers_mutex (),
+ m_saved_registers_map (),
+ m_next_saved_registers_id (1)
{
+ assert(is_platform && "must be lldb-platform if debugger is not specified");
}
GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform,
- const lldb::PlatformSP& platform_sp) :
+ const lldb::PlatformSP& platform_sp,
+ lldb::DebuggerSP &debugger_sp) :
GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
m_platform_sp (platform_sp),
m_async_thread (LLDB_INVALID_HOST_THREAD),
@@ -66,9 +112,24 @@ GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform,
m_proc_infos (),
m_proc_infos_index (0),
m_port_map (),
- m_port_offset(0)
+ m_port_offset(0),
+ m_current_tid (LLDB_INVALID_THREAD_ID),
+ m_continue_tid (LLDB_INVALID_THREAD_ID),
+ m_debugged_process_mutex (Mutex::eMutexTypeRecursive),
+ m_debugged_process_sp (),
+ m_debugger_sp (debugger_sp),
+ m_stdio_communication ("process.stdio"),
+ m_exit_now (false),
+ m_inferior_prev_state (StateType::eStateInvalid),
+ m_thread_suffix_supported (false),
+ m_list_threads_in_stop_reply (false),
+ m_active_auxv_buffer_sp (),
+ m_saved_registers_mutex (),
+ m_saved_registers_map (),
+ m_next_saved_registers_id (1)
{
assert(platform_sp);
+ assert((is_platform || debugger_sp) && "must specify non-NULL debugger_sp when lldb-gdbserver");
}
//----------------------------------------------------------------------
@@ -78,37 +139,14 @@ GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
{
}
-
-//void *
-//GDBRemoteCommunicationServer::AsyncThread (void *arg)
-//{
-// GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
-//
-// Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
-// if (log)
-// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
-//
-// StringExtractorGDBRemote packet;
-//
-// while ()
-// {
-// if (packet.
-// }
-//
-// if (log)
-// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
-//
-// process->m_async_thread = LLDB_INVALID_HOST_THREAD;
-// return NULL;
-//}
-//
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
Error &error,
bool &interrupt,
bool &quit)
{
StringExtractorGDBRemote packet;
+
PacketResult packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
if (packet_result == PacketResult::Success)
{
@@ -124,11 +162,6 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
quit = true;
break;
- case StringExtractorGDBRemote::eServerPacketType_interrupt:
- error.SetErrorString("interrupt received");
- interrupt = true;
- break;
-
default:
case StringExtractorGDBRemote::eServerPacketType_unimplemented:
packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str());
@@ -164,6 +197,7 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
case StringExtractorGDBRemote::eServerPacketType_k:
packet_result = Handle_k (packet);
+ quit = true;
break;
case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
@@ -174,6 +208,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
packet_result = Handle_qGroupName (packet);
break;
+ case StringExtractorGDBRemote::eServerPacketType_qProcessInfo:
+ packet_result = Handle_qProcessInfo (packet);
+ break;
+
case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
packet_result = Handle_qProcessInfoPID (packet);
break;
@@ -202,6 +240,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
packet_result = Handle_QSetDisableASLR (packet);
break;
+ case StringExtractorGDBRemote::eServerPacketType_QSetDetachOnError:
+ packet_result = Handle_QSetDetachOnError (packet);
+ break;
+
case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
packet_result = Handle_QSetSTDIN (packet);
break;
@@ -234,6 +276,26 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
packet_result = Handle_qPlatform_shell (packet);
break;
+ case StringExtractorGDBRemote::eServerPacketType_C:
+ packet_result = Handle_C (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_c:
+ packet_result = Handle_c (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_vCont:
+ packet_result = Handle_vCont (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_vCont_actions:
+ packet_result = Handle_vCont_actions (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_stop_reason: // ?
+ packet_result = Handle_stop_reason (packet);
+ break;
+
case StringExtractorGDBRemote::eServerPacketType_vFile_open:
packet_result = Handle_vFile_Open (packet);
break;
@@ -277,6 +339,96 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
case StringExtractorGDBRemote::eServerPacketType_vFile_unlink:
packet_result = Handle_vFile_unlink (packet);
break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qRegisterInfo:
+ packet_result = Handle_qRegisterInfo (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qfThreadInfo:
+ packet_result = Handle_qfThreadInfo (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qsThreadInfo:
+ packet_result = Handle_qsThreadInfo (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_p:
+ packet_result = Handle_p (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_P:
+ packet_result = Handle_P (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_H:
+ packet_result = Handle_H (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_m:
+ packet_result = Handle_m (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_M:
+ packet_result = Handle_M (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfoSupported:
+ packet_result = Handle_qMemoryRegionInfoSupported (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo:
+ packet_result = Handle_qMemoryRegionInfo (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_interrupt:
+ if (IsGdbServer ())
+ packet_result = Handle_interrupt (packet);
+ else
+ {
+ error.SetErrorString("interrupt received");
+ interrupt = true;
+ }
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_Z:
+ packet_result = Handle_Z (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_z:
+ packet_result = Handle_z (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_s:
+ packet_result = Handle_s (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qSupported:
+ packet_result = Handle_qSupported (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported:
+ packet_result = Handle_QThreadSuffixSupported (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply:
+ packet_result = Handle_QListThreadsInStopReply (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read:
+ packet_result = Handle_qXfer_auxv_read (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_QSaveRegisterState:
+ packet_result = Handle_QSaveRegisterState (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState:
+ packet_result = Handle_QRestoreRegisterState (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_vAttach:
+ packet_result = Handle_vAttach (packet);
+ break;
}
}
else
@@ -291,7 +443,12 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
error.SetErrorString("timeout");
}
}
- return packet_result == PacketResult::Success;
+
+ // Check if anything occurred that would force us to want to exit.
+ if (m_exit_now)
+ quit = true;
+
+ return packet_result;
}
lldb_private::Error
@@ -314,6 +471,96 @@ GDBRemoteCommunicationServer::SetLaunchFlags (unsigned int launch_flags)
lldb_private::Error
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 ();
+ else
+ return LaunchPlatformProcess ();
+}
+
+lldb_private::Error
+GDBRemoteCommunicationServer::LaunchDebugServerProcess ()
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
+ return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__);
+
+ lldb_private::Error error;
+ {
+ Mutex::Locker locker (m_debugged_process_mutex);
+ assert (!m_debugged_process_sp && "lldb-gdbserver creating debugged process but one already exists");
+ error = m_platform_sp->LaunchNativeProcess (
+ m_process_launch_info,
+ *this,
+ m_debugged_process_sp);
+ }
+
+ if (!error.Success ())
+ {
+ fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
+ return error;
+ }
+
+ // Setup stdout/stderr mapping from inferior.
+ 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);
+ }
+
+ printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID ());
+
+ // Add to list of spawned processes.
+ lldb::pid_t pid;
+ 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__);
+
+ }
+
+ return error;
+}
+
+lldb_private::Error
+GDBRemoteCommunicationServer::LaunchPlatformProcess ()
+{
if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__);
@@ -337,13 +584,571 @@ GDBRemoteCommunicationServer::LaunchProcess ()
lldb::pid_t pid;
if ( (pid = m_process_launch_info.GetProcessID()) != LLDB_INVALID_PROCESS_ID )
{
+ // add to spawned pids
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ m_spawned_pids.insert(pid);
+ }
+ }
+
+ return error;
+}
+
+lldb_private::Error
+GDBRemoteCommunicationServer::AttachToProcess (lldb::pid_t pid)
+{
+ Error error;
+
+ if (!IsGdbServer ())
+ {
+ error.SetErrorString("cannot AttachToProcess () unless process is lldb-gdbserver");
+ return error;
+ }
+
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64, __FUNCTION__, pid);
+
+ // Scope for mutex locker.
+ {
+ // Before we try to attach, make sure we aren't already monitoring something else.
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (!m_spawned_pids.empty ())
+ {
+ error.SetErrorStringWithFormat ("cannot attach to a process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, *m_spawned_pids.begin());
+ return error;
+ }
+
+ // Try to attach.
+ error = m_platform_sp->AttachNativeProcess (pid, *this, m_debugged_process_sp);
+ if (!error.Success ())
+ {
+ fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ());
+ return error;
+ }
+
+ // Setup stdout/stderr mapping from inferior.
+ 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);
+ }
+
+ printf ("Attached to process %" PRIu64 "...\n", pid);
+
+ // Add to list of spawned processes.
+ assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed");
+ m_spawned_pids.insert (pid);
+
+ return error;
+ }
+}
+
+void
+GDBRemoteCommunicationServer::InitializeDelegate (lldb_private::NativeProcessProtocol *process)
+{
+ assert (process && "process cannot be NULL");
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ {
+ log->Printf ("GDBRemoteCommunicationServer::%s called with NativeProcessProtocol pid %" PRIu64 ", current state: %s",
+ __FUNCTION__,
+ process->GetID (),
+ StateAsCString (process->GetState ()));
+ }
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::SendWResponse (lldb_private::NativeProcessProtocol *process)
+{
+ assert (process && "process cannot be NULL");
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // send W notification
+ ExitType exit_type = ExitType::eExitTypeInvalid;
+ int return_code = 0;
+ std::string exit_description;
+
+ const bool got_exit_info = process->GetExitStatus (&exit_type, &return_code, exit_description);
+ if (!got_exit_info)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 ", failed to retrieve process exit status", __FUNCTION__, process->GetID ());
+
+ StreamGDBRemote response;
+ response.PutChar ('E');
+ response.PutHex8 (GDBRemoteServerError::eErrorExitStatus);
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+ }
+ else
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 ", returning exit type %d, return code %d [%s]", __FUNCTION__, process->GetID (), exit_type, return_code, exit_description.c_str ());
+
+ StreamGDBRemote response;
+
+ 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::eExitTypeInvalid:
+ default: return_type_code = 'E'; break;
+ }
+ response.PutChar (return_type_code);
+
+ // POSIX exit status limited to unsigned 8 bits.
+ response.PutHex8 (return_code);
+
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+ }
+}
+
+static void
+AppendHexValue (StreamString &response, const uint8_t* buf, uint32_t buf_size, bool swap)
+{
+ int64_t i;
+ if (swap)
+ {
+ for (i = buf_size-1; i >= 0; i--)
+ response.PutHex8 (buf[i]);
+ }
+ else
+ {
+ for (i = 0; i < buf_size; i++)
+ response.PutHex8 (buf[i]);
+ }
+}
+
+static void
+WriteRegisterValueInHexFixedWidth (StreamString &response,
+ NativeRegisterContextSP &reg_ctx_sp,
+ const RegisterInfo &reg_info,
+ const RegisterValue *reg_value_p)
+{
+ RegisterValue reg_value;
+ if (!reg_value_p)
+ {
+ Error error = reg_ctx_sp->ReadRegister (&reg_info, reg_value);
+ if (error.Success ())
+ reg_value_p = &reg_value;
+ // else log.
+ }
+
+ if (reg_value_p)
+ {
+ AppendHexValue (response, (const uint8_t*) reg_value_p->GetBytes (), reg_value_p->GetByteSize (), false);
+ }
+ else
+ {
+ // Zero-out any unreadable values.
+ if (reg_info.byte_size > 0)
+ {
+ std::basic_string<uint8_t> zeros(reg_info.byte_size, '\0');
+ AppendHexValue (response, zeros.data(), zeros.size(), false);
+ }
+ }
+}
+
+// WriteGdbRegnumWithFixedWidthHexRegisterValue (response, reg_ctx_sp, *reg_info_p, reg_value);
+
+
+static void
+WriteGdbRegnumWithFixedWidthHexRegisterValue (StreamString &response,
+ NativeRegisterContextSP &reg_ctx_sp,
+ const RegisterInfo &reg_info,
+ const RegisterValue &reg_value)
+{
+ // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX
+ // gdb register number, and VVVVVVVV is the correct number of hex bytes
+ // as ASCII for the register value.
+ if (reg_info.kinds[eRegisterKindGDB] == LLDB_INVALID_REGNUM)
+ return;
+
+ response.Printf ("%.02x:", reg_info.kinds[eRegisterKindGDB]);
+ WriteRegisterValueInHexFixedWidth (response, reg_ctx_sp, reg_info, &reg_value);
+ response.PutChar (';');
+}
+
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+
+ // Ensure we're llgs.
+ if (!IsGdbServer ())
+ {
+ // Only supported on llgs
+ return SendUnimplementedResponse ("");
+ }
+
+ // Ensure we have a debugged process.
+ if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse (50);
+
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s preparing packet for pid %" PRIu64 " tid %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID (), tid);
+
+ // Ensure we can get info on the given thread.
+ NativeThreadProtocolSP thread_sp (m_debugged_process_sp->GetThreadByID (tid));
+ if (!thread_sp)
+ return SendErrorResponse (51);
+
+ // Grab the reason this thread stopped.
+ struct ThreadStopInfo tid_stop_info;
+ if (!thread_sp->GetStopReason (tid_stop_info))
+ return SendErrorResponse (52);
+
+ const bool did_exec = tid_stop_info.reason == eStopReasonExec;
+ // FIXME implement register handling for exec'd inferiors.
+ // if (did_exec)
+ // {
+ // const bool force = true;
+ // InitializeRegisters(force);
+ // }
+
+ StreamString response;
+ // Output the T packet with the thread
+ response.PutChar ('T');
+ int signum = tid_stop_info.details.signal.signo;
+ if (log)
+ {
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64,
+ __FUNCTION__,
+ m_debugged_process_sp->GetID (),
+ tid,
+ signum,
+ tid_stop_info.reason,
+ tid_stop_info.details.exception.type);
+ }
+
+ switch (tid_stop_info.reason)
+ {
+ case eStopReasonSignal:
+ case eStopReasonException:
+ signum = thread_sp->TranslateStopInfoToGdbSignal (tid_stop_info);
+ break;
+ default:
+ signum = 0;
+ if (log)
+ {
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " tid %" PRIu64 " has stop reason %d, using signo = 0 in stop reply response",
+ __FUNCTION__,
+ m_debugged_process_sp->GetID (),
+ tid,
+ tid_stop_info.reason);
+ }
+ break;
+ }
+
+ // Print the signal number.
+ response.PutHex8 (signum & 0xff);
+
+ // Include the 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])
+ {
+ size_t thread_name_len = strlen(thread_name);
+
+ if (::strcspn (thread_name, "$#+-;:") == thread_name_len)
+ {
+ response.PutCString ("name:");
+ response.PutCString (thread_name);
+ }
+ else
+ {
+ // The thread name contains special chars, send as hex bytes.
+ response.PutCString ("hexname:");
+ response.PutCStringAsRawHex8 (thread_name);
+ }
+ response.PutChar (';');
+ }
+
+ // FIXME look for analog
+ // thread_identifier_info_data_t thread_ident_info;
+ // if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info))
+ // {
+ // if (thread_ident_info.dispatch_qaddr != 0)
+ // ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';';
+ // }
+
+ // If a 'QListThreadsInStopReply' was sent to enable this feature, we
+ // will send all thread IDs back in the "threads" key whose value is
+ // a list of hex thread IDs separated by commas:
+ // "threads:10a,10b,10c;"
+ // This will save the debugger from having to send a pair of qfThreadInfo
+ // and qsThreadInfo packets, but it also might take a lot of room in the
+ // stop reply packet, so it must be enabled only on systems where there
+ // are no limits on packet lengths.
+ if (m_list_threads_in_stop_reply)
+ {
+ response.PutCString ("threads:");
+
+ uint32_t thread_index = 0;
+ NativeThreadProtocolSP listed_thread_sp;
+ for (listed_thread_sp = m_debugged_process_sp->GetThreadAtIndex (thread_index); listed_thread_sp; ++thread_index, listed_thread_sp = m_debugged_process_sp->GetThreadAtIndex (thread_index))
+ {
+ if (thread_index > 0)
+ response.PutChar (',');
+ response.Printf ("%" PRIx64, listed_thread_sp->GetID ());
+ }
+ response.PutChar (';');
+ }
+
+ //
+ // Expedite registers.
+ //
+
+ // Grab the register context.
+ NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext ();
+ if (reg_ctx_sp)
+ {
+ // Expedite all registers in the first register set (i.e. should be GPRs) that are not contained in other registers.
+ const RegisterSet *reg_set_p;
+ if (reg_ctx_sp->GetRegisterSetCount () > 0 && ((reg_set_p = reg_ctx_sp->GetRegisterSet (0)) != nullptr))
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s expediting registers from set '%s' (registers set count: %zu)", __FUNCTION__, reg_set_p->name ? reg_set_p->name : "<unnamed-set>", reg_set_p->num_registers);
+
+ for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p)
+ {
+ const RegisterInfo *const reg_info_p = reg_ctx_sp->GetRegisterInfoAtIndex (*reg_num_p);
+ if (reg_info_p == nullptr)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed to get register info for register set '%s', register index %" PRIu32, __FUNCTION__, reg_set_p->name ? reg_set_p->name : "<unnamed-set>", *reg_num_p);
+ }
+ else if (reg_info_p->value_regs == nullptr)
+ {
+ // Only expediate registers that are not contained in other registers.
+ RegisterValue reg_value;
+ Error error = reg_ctx_sp->ReadRegister (reg_info_p, reg_value);
+ if (error.Success ())
+ WriteGdbRegnumWithFixedWidthHexRegisterValue (response, reg_ctx_sp, *reg_info_p, reg_value);
+ else
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed to read register '%s' index %" PRIu32 ": %s", __FUNCTION__, reg_info_p->name ? reg_info_p->name : "<unnamed-register>", *reg_num_p, error.AsCString ());
+
+ }
+ }
+ }
+ }
+ }
+
+ if (did_exec)
+ {
+ response.PutCString ("reason:exec;");
+ }
+ else if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type)
+ {
+ response.PutCString ("metype:");
+ response.PutHex64 (tid_stop_info.details.exception.type);
+ response.PutCString (";mecount:");
+ response.PutHex32 (tid_stop_info.details.exception.data_count);
+ response.PutChar (';');
+
+ for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i)
+ {
+ response.PutCString ("medata:");
+ response.PutHex64 (tid_stop_info.details.exception.data[i]);
+ response.PutChar (';');
+ }
+ }
+
+ return SendPacketNoLock (response.GetData(), response.GetSize());
+}
+
+void
+GDBRemoteCommunicationServer::HandleInferiorState_Exited (lldb_private::NativeProcessProtocol *process)
+{
+ assert (process && "process cannot be NULL");
+
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s called", __FUNCTION__);
+
+ // Send the exit result, and don't flush output.
+ // Note: flushing output here would join the inferior stdio reflection thread, which
+ // would gunk up the waitpid monitor thread that is calling this.
+ PacketResult result = SendStopReasonForState (StateType::eStateExited, false);
+ if (result != PacketResult::Success)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed to send stop notification for PID %" PRIu64 ", state: eStateExited", __FUNCTION__, process->GetID ());
+ }
+
+ // Remove the process from the list of spawned pids.
+ {
Mutex::Locker locker (m_spawned_pids_mutex);
- m_spawned_pids.insert(pid);
+ if (m_spawned_pids.erase (process->GetID ()) < 1)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed to remove PID %" PRIu64 " from the spawned pids list", __FUNCTION__, process->GetID ());
+
+ }
}
+ // FIXME can't do this yet - since process state propagation is currently
+ // synchronous, it is running off the NativeProcessProtocol's innards and
+ // will tear down the NPP while it still has code to execute.
+#if 0
+ // Clear the NativeProcessProtocol pointer.
+ {
+ Mutex::Locker locker (m_debugged_process_mutex);
+ m_debugged_process_sp.reset();
+ }
+#endif
+
+ // Close the pipe to the inferior terminal i/o if we launched it
+ // and set one up. Otherwise, 'k' and its flush of stdio could
+ // end up waiting on a thread join that will never end. Consider
+ // adding a timeout to the connection thread join call so we
+ // can avoid that scenario altogether.
+ MaybeCloseInferiorTerminalConnection ();
+
+ // We are ready to exit the debug monitor.
+ m_exit_now = true;
+}
+
+void
+GDBRemoteCommunicationServer::HandleInferiorState_Stopped (lldb_private::NativeProcessProtocol *process)
+{
+ assert (process && "process cannot be NULL");
+
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s called", __FUNCTION__);
+
+ // Send the stop reason unless this is the stop after the
+ // launch or attach.
+ switch (m_inferior_prev_state)
+ {
+ case eStateLaunching:
+ case eStateAttaching:
+ // Don't send anything per debugserver behavior.
+ break;
+ default:
+ // In all other cases, send the stop reason.
+ PacketResult result = SendStopReasonForState (StateType::eStateStopped, false);
+ if (result != PacketResult::Success)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed to send stop notification for PID %" PRIu64 ", state: eStateExited", __FUNCTION__, process->GetID ());
+ }
+ break;
+ }
+}
+
+void
+GDBRemoteCommunicationServer::ProcessStateChanged (lldb_private::NativeProcessProtocol *process, lldb::StateType state)
+{
+ assert (process && "process cannot be NULL");
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ {
+ log->Printf ("GDBRemoteCommunicationServer::%s called with NativeProcessProtocol pid %" PRIu64 ", state: %s",
+ __FUNCTION__,
+ process->GetID (),
+ StateAsCString (state));
+ }
+
+ switch (state)
+ {
+ case StateType::eStateExited:
+ HandleInferiorState_Exited (process);
+ break;
+
+ case StateType::eStateStopped:
+ HandleInferiorState_Stopped (process);
+ break;
+
+ default:
+ if (log)
+ {
+ log->Printf ("GDBRemoteCommunicationServer::%s didn't handle state change for pid %" PRIu64 ", new state: %s",
+ __FUNCTION__,
+ process->GetID (),
+ StateAsCString (state));
+ }
+ break;
+ }
+
+ // Remember the previous state reported to us.
+ m_inferior_prev_state = state;
+}
+
+void
+GDBRemoteCommunicationServer::DidExec (NativeProcessProtocol *process)
+{
+ ClearProcessSpecificData ();
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::SendONotification (const char *buffer, uint32_t len)
+{
+ if ((buffer == nullptr) || (len == 0))
+ {
+ // Nothing to send.
+ return PacketResult::Success;
+ }
+
+ StreamString response;
+ response.PutChar ('O');
+ response.PutBytesAsRawHex8 (buffer, len);
+
+ return SendPacketNoLock (response.GetData (), response.GetSize ());
+}
+
+lldb_private::Error
+GDBRemoteCommunicationServer::SetSTDIOFileDescriptor (int fd)
+{
+ Error error;
+
+ // Set up the Read Thread for reading/handling process I/O
+ std::unique_ptr<ConnectionFileDescriptor> conn_up (new ConnectionFileDescriptor (fd, true));
+ if (!conn_up)
+ {
+ error.SetErrorString ("failed to create ConnectionFileDescriptor");
+ return error;
+ }
+
+ m_stdio_communication.SetConnection (conn_up.release());
+ if (!m_stdio_communication.IsConnected ())
+ {
+ error.SetErrorString ("failed to set connection for inferior I/O communication");
+ return error;
+ }
+
+ m_stdio_communication.SetReadThreadBytesReceivedCallback (STDIOReadThreadBytesReceived, this);
+ m_stdio_communication.StartReadThread();
+
return error;
}
+void
+GDBRemoteCommunicationServer::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len)
+{
+ GDBRemoteCommunicationServer *server = reinterpret_cast<GDBRemoteCommunicationServer*> (baton);
+ static_cast<void> (server->SendONotification (static_cast<const char *>(src), src_len));
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
{
@@ -351,6 +1156,7 @@ GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
return SendPacketNoLock ("", 0);
}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
{
@@ -360,6 +1166,14 @@ GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
return SendPacketNoLock (packet, packet_len);
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::SendIllFormedResponse (const StringExtractorGDBRemote &failed_packet, const char *message)
+{
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", __FUNCTION__, failed_packet.GetStringRef ().c_str (), message ? message : "");
+ return SendErrorResponse (0x03);
+}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendOKResponse ()
@@ -380,10 +1194,10 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
// $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
- ArchSpec host_arch (Host::GetArchitecture ());
+ ArchSpec host_arch(HostInfo::GetArchitecture());
const llvm::Triple &host_triple = host_arch.GetTriple();
response.PutCString("triple:");
- response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
+ response.PutCString(host_triple.getTriple().c_str());
response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
const char* distribution_id = host_arch.GetDistributionId ().AsCString ();
@@ -394,6 +1208,8 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
response.PutCString(";");
}
+ // Only send out MachO info when lldb-platform/llgs is running on a MachO host.
+#if defined(__APPLE__)
uint32_t cpu = host_arch.GetMachOCPUType();
uint32_t sub = host_arch.GetMachOCPUSubType();
if (cpu != LLDB_INVALID_CPUTYPE)
@@ -405,6 +1221,9 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
response.Printf("watchpoint_exceptions_received:before;"); // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
else
response.Printf("watchpoint_exceptions_received:after;");
+#else
+ response.Printf("watchpoint_exceptions_received:after;");
+#endif
switch (lldb::endian::InlHostByteOrder())
{
@@ -417,7 +1236,7 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
uint32_t major = UINT32_MAX;
uint32_t minor = UINT32_MAX;
uint32_t update = UINT32_MAX;
- if (Host::GetOSVersion (major, minor, update))
+ if (HostInfo::GetOSVersion(major, minor, update))
{
if (major != UINT32_MAX)
{
@@ -433,39 +1252,41 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
}
std::string s;
- if (Host::GetOSBuildString (s))
+#if !defined(__linux__)
+ if (HostInfo::GetOSBuildString(s))
{
response.PutCString ("os_build:");
response.PutCStringAsRawHex8(s.c_str());
response.PutChar(';');
}
- if (Host::GetOSKernelDescription (s))
+ if (HostInfo::GetOSKernelDescription(s))
{
response.PutCString ("os_kernel:");
response.PutCStringAsRawHex8(s.c_str());
response.PutChar(';');
}
+#endif
+
#if defined(__APPLE__)
-#if defined(__arm__)
+#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
// For iOS devices, we are connected through a USB Mux so we never pretend
// to actually have a hostname as far as the remote lldb that is connecting
// to this lldb-platform is concerned
response.PutCString ("hostname:");
- response.PutCStringAsRawHex8("localhost");
+ response.PutCStringAsRawHex8("127.0.0.1");
response.PutChar(';');
-#else // #if defined(__arm__)
- if (Host::GetHostname (s))
+#else // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
+ if (HostInfo::GetHostname(s))
{
response.PutCString ("hostname:");
response.PutCStringAsRawHex8(s.c_str());
response.PutChar(';');
}
-
-#endif // #if defined(__arm__)
+#endif // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
#else // #if defined(__APPLE__)
- if (Host::GetHostname (s))
+ if (HostInfo::GetHostname(s))
{
response.PutCString ("hostname:");
response.PutCStringAsRawHex8(s.c_str());
@@ -494,11 +1315,105 @@ CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &r
{
const llvm::Triple &proc_triple = proc_arch.GetTriple();
response.PutCString("triple:");
- response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
+ response.PutCString(proc_triple.getTriple().c_str());
response.PutChar(';');
}
}
+static void
+CreateProcessInfoResponse_DebugServerStyle (const ProcessInstanceInfo &proc_info, StreamString &response)
+{
+ response.Printf ("pid:%" PRIx64 ";parent-pid:%" PRIx64 ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;",
+ proc_info.GetProcessID(),
+ proc_info.GetParentProcessID(),
+ proc_info.GetUserID(),
+ proc_info.GetGroupID(),
+ proc_info.GetEffectiveUserID(),
+ proc_info.GetEffectiveGroupID());
+
+ const ArchSpec &proc_arch = proc_info.GetArchitecture();
+ if (proc_arch.IsValid())
+ {
+ const llvm::Triple &proc_triple = proc_arch.GetTriple();
+#if defined(__APPLE__)
+ // We'll send cputype/cpusubtype.
+ const uint32_t cpu_type = proc_arch.GetMachOCPUType();
+ if (cpu_type != 0)
+ response.Printf ("cputype:%" PRIx32 ";", cpu_type);
+
+ const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType();
+ if (cpu_subtype != 0)
+ response.Printf ("cpusubtype:%" PRIx32 ";", cpu_subtype);
+
+
+ const std::string vendor = proc_triple.getVendorName ();
+ if (!vendor.empty ())
+ response.Printf ("vendor:%s;", vendor.c_str ());
+#else
+ // We'll send the triple.
+ response.Printf ("triple:%s;", proc_triple.getTriple().c_str ());
+#endif
+ std::string ostype = proc_triple.getOSName ();
+ // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64.
+ if (proc_triple.getVendor () == llvm::Triple::Apple)
+ {
+ switch (proc_triple.getArch ())
+ {
+ case llvm::Triple::arm:
+ case llvm::Triple::aarch64:
+ ostype = "ios";
+ break;
+ default:
+ // No change.
+ break;
+ }
+ }
+ response.Printf ("ostype:%s;", ostype.c_str ());
+
+
+ switch (proc_arch.GetByteOrder ())
+ {
+ case lldb::eByteOrderLittle: response.PutCString ("endian:little;"); break;
+ case lldb::eByteOrderBig: response.PutCString ("endian:big;"); break;
+ case lldb::eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
+ default:
+ // Nothing.
+ break;
+ }
+
+ if (proc_triple.isArch64Bit ())
+ response.PutCString ("ptrsize:8;");
+ else if (proc_triple.isArch32Bit ())
+ response.PutCString ("ptrsize:4;");
+ else if (proc_triple.isArch16Bit ())
+ response.PutCString ("ptrsize:2;");
+ }
+
+}
+
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_qProcessInfo (StringExtractorGDBRemote &packet)
+{
+ // Only the gdb server handles this.
+ if (!IsGdbServer ())
+ return SendUnimplementedResponse (packet.GetStringRef ().c_str ());
+
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse (68);
+
+ ProcessInstanceInfo proc_info;
+ if (Host::GetProcessInfo (m_debugged_process_sp->GetID (), proc_info))
+ {
+ StreamString response;
+ CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
+ return SendPacketNoLock (response.GetData (), response.GetSize ());
+ }
+
+ return SendErrorResponse (1);
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
{
@@ -635,19 +1550,21 @@ GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &pa
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
{
+#if !defined(LLDB_DISABLE_POSIX)
// Packet format: "qUserName:%i" where %i is the uid
packet.SetFilePos(::strlen ("qUserName:"));
uint32_t uid = packet.GetU32 (UINT32_MAX);
if (uid != UINT32_MAX)
{
std::string name;
- if (Host::GetUserName (uid, name))
+ if (HostInfo::LookupUserName(uid, name))
{
StreamString response;
response.PutCStringAsRawHex8 (name.c_str());
return SendPacketNoLock (response.GetData(), response.GetSize());
}
}
+#endif
return SendErrorResponse (5);
}
@@ -655,19 +1572,21 @@ GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
{
+#if !defined(LLDB_DISABLE_POSIX)
// Packet format: "qGroupName:%i" where %i is the gid
packet.SetFilePos(::strlen ("qGroupName:"));
uint32_t gid = packet.GetU32 (UINT32_MAX);
if (gid != UINT32_MAX)
{
std::string name;
- if (Host::GetGroupName (gid, name))
+ if (HostInfo::LookupGroupName(gid, name))
{
StreamString response;
response.PutCStringAsRawHex8 (name.c_str());
return SendPacketNoLock (response.GetData(), response.GetSize());
}
}
+#endif
return SendErrorResponse (6);
}
@@ -708,27 +1627,6 @@ GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packe
return SendErrorResponse (7);
}
-
-static void *
-AcceptPortFromInferior (void *arg)
-{
- const char *connect_url = (const char *)arg;
- ConnectionFileDescriptor file_conn;
- Error error;
- if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
- {
- char pid_str[256];
- ::memset (pid_str, 0, sizeof(pid_str));
- ConnectionStatus status;
- const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL);
- if (pid_str_len > 0)
- {
- int pid = atoi (pid_str);
- return (void *)(intptr_t)pid;
- }
- }
- return NULL;
-}
//
//static bool
//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
@@ -772,6 +1670,9 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
// separated hex encoded argument value list, but we will stay true to the
// documented version of the 'A' packet here...
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ int actual_arg_index = 0;
+
packet.SetFilePos(1); // Skip the 'A'
bool success = true;
while (success && packet.GetBytesLeft() > 0)
@@ -788,7 +1689,7 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
success = false;
else
{
- // Decode the argument index. We ignore this really becuase
+ // Decode the argument index. We ignore this really because
// who would really send down the arguments in a random order???
const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
if (arg_idx == UINT32_MAX)
@@ -804,11 +1705,11 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
// back into a UTF8 string and make sure the length
// matches the one supplied in the packet
std::string arg;
- if (packet.GetHexByteString(arg) != (arg_len / 2))
+ if (packet.GetHexByteStringFixedLength(arg, arg_len) != (arg_len / 2))
success = false;
else
{
- // If there are any bytes lft
+ // If there are any bytes left
if (packet.GetBytesLeft())
{
if (packet.GetChar() != ',')
@@ -820,6 +1721,9 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
if (arg_idx == 0)
m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s added arg %d: \"%s\"", __FUNCTION__, actual_arg_index, arg.c_str ());
+ ++actual_arg_index;
}
}
}
@@ -830,15 +1734,20 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
if (success)
{
- // FIXME: remove linux restriction once eLaunchFlagDebug is supported
-#if !defined (__linux__)
- m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
-#endif
m_process_launch_error = LaunchProcess ();
if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
{
return SendOKResponse ();
}
+ else
+ {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServer::%s failed to launch exe: %s",
+ __FUNCTION__,
+ m_process_launch_error.AsCString());
+
+ }
}
return SendErrorResponse (8);
}
@@ -846,22 +1755,51 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
{
- lldb::pid_t pid = m_process_launch_info.GetProcessID();
StreamString response;
- response.Printf("QC%" PRIx64, pid);
- if (m_is_platform)
+
+ if (IsGdbServer ())
+ {
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse (68);
+
+ // Make sure we set the current thread so g and p packets return
+ // the data the gdb will expect.
+ lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID ();
+ SetCurrentThreadID (tid);
+
+ NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetCurrentThread ();
+ if (!thread_sp)
+ return SendErrorResponse (69);
+
+ response.Printf ("QC%" PRIx64, thread_sp->GetID ());
+ }
+ else
{
- // If we launch a process and this GDB server is acting as a platform,
- // then we need to clear the process launch state so we can start
- // launching another process. In order to launch a process a bunch or
- // packets need to be sent: environment packets, working directory,
- // disable ASLR, and many more settings. When we launch a process we
- // then need to know when to clear this information. Currently we are
- // selecting the 'qC' packet as that packet which seems to make the most
- // sense.
- if (pid != LLDB_INVALID_PROCESS_ID)
+ // NOTE: lldb should now be using qProcessInfo for process IDs. This path here
+ // should not be used. It is reporting process id instead of thread id. The
+ // correct answer doesn't seem to make much sense for lldb-platform.
+ // CONSIDER: flip to "unsupported".
+ lldb::pid_t pid = m_process_launch_info.GetProcessID();
+ response.Printf("QC%" PRIx64, pid);
+
+ // this should always be platform here
+ assert (m_is_platform && "this code path should only be traversed for lldb-platform");
+
+ if (m_is_platform)
{
- m_process_launch_info.Clear();
+ // If we launch a process and this GDB server is acting as a platform,
+ // then we need to clear the process launch state so we can start
+ // launching another process. In order to launch a process a bunch or
+ // packets need to be sent: environment packets, working directory,
+ // disable ASLR, and many more settings. When we launch a process we
+ // then need to know when to clear this information. Currently we are
+ // selecting the 'qC' packet as that packet which seems to make the most
+ // sense.
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ {
+ m_process_launch_info.Clear();
+ }
}
}
return SendPacketNoLock (response.GetData(), response.GetSize());
@@ -912,17 +1850,21 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
#ifdef _WIN32
return SendErrorResponse(9);
#else
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+
// Spawn a local debugserver as a platform so we can then attach or launch
// a process...
if (m_is_platform)
{
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s() called", __FUNCTION__);
+
// Sleep and wait a bit for debugserver to start to listen...
ConnectionFileDescriptor file_conn;
- Error error;
std::string hostname;
// TODO: /tmp/ should not be hardcoded. User might want to override /tmp
- // with the TMPDIR environnement variable
+ // with the TMPDIR environment variable
packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
std::string name;
std::string value;
@@ -940,53 +1882,57 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
// Spawn a new thread to accept the port that gets bound after
// binding to port 0 (zero).
- if (error.Success())
- {
- // Spawn a debugserver and try to get the port it listens to.
- ProcessLaunchInfo debugserver_launch_info;
- if (hostname.empty())
- hostname = "localhost";
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
- if (log)
- log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);
+ // Spawn a debugserver and try to get the port it listens to.
+ ProcessLaunchInfo debugserver_launch_info;
+ if (hostname.empty())
+ hostname = "127.0.0.1";
+ if (log)
+ log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);
- debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
-
- error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(),
- port,
- debugserver_launch_info,
- port);
+ debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
- lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
+ Error error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(),
+ port,
+ debugserver_launch_info,
+ port);
+ lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
- if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- m_spawned_pids.insert(debugserver_pid);
- if (port > 0)
- AssociatePortWithProcess(port, debugserver_pid);
- }
- else
- {
- if (port > 0)
- FreePort (port);
- }
- if (error.Success())
- {
- char response[256];
- const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
- assert (response_len < sizeof(response));
- PacketResult packet_result = SendPacketNoLock (response, response_len);
+ if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ m_spawned_pids.insert(debugserver_pid);
+ if (port > 0)
+ AssociatePortWithProcess(port, debugserver_pid);
+ }
+ else
+ {
+ if (port > 0)
+ FreePort (port);
+ }
- if (packet_result != PacketResult::Success)
- {
- if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
- ::kill (debugserver_pid, SIGINT);
- }
- return packet_result;
+ if (error.Success())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
+
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
+ assert (response_len < (int)sizeof(response));
+ PacketResult packet_result = SendPacketNoLock (response, response_len);
+
+ if (packet_result != PacketResult::Success)
+ {
+ if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ ::kill (debugserver_pid, SIGINT);
}
+ return packet_result;
+ }
+ else
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
}
}
return SendErrorResponse (9);
@@ -1027,7 +1973,7 @@ GDBRemoteCommunicationServer::KillSpawnedProcess (lldb::pid_t pid)
return true;
}
- // the launched process still lives. Now try killling it again,
+ // the launched process still lives. Now try killing it again,
// this time with an unblockable signal.
Host::Kill (pid, SIGKILL);
@@ -1107,8 +2053,11 @@ GDBRemoteCommunicationServer::Handle_k (StringExtractorGDBRemote &packet)
}
}
- // TODO figure out how to shut down gracefully at this point
- return SendOKResponse ();
+ FlushInferiorOutput ();
+
+ // No OK response for kill packet.
+ // return SendOKResponse ();
+ return PacketResult::Success;
}
GDBRemoteCommunication::PacketResult
@@ -1223,7 +2172,7 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen ("QSetSTDIN:"));
- ProcessLaunchInfo::FileAction file_action;
+ FileAction file_action;
std::string path;
packet.GetHexByteString(path);
const bool read = false;
@@ -1240,7 +2189,7 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen ("QSetSTDOUT:"));
- ProcessLaunchInfo::FileAction file_action;
+ FileAction file_action;
std::string path;
packet.GetHexByteString(path);
const bool read = true;
@@ -1257,7 +2206,7 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen ("QSetSTDERR:"));
- ProcessLaunchInfo::FileAction file_action;
+ FileAction file_action;
std::string path;
packet.GetHexByteString(path);
const bool read = true;
@@ -1271,6 +2220,288 @@ GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packe
}
GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_C (StringExtractorGDBRemote &packet)
+{
+ if (!IsGdbServer ())
+ return SendUnimplementedResponse (packet.GetStringRef().c_str());
+
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s called", __FUNCTION__);
+
+ // Ensure we have a native process.
+ if (!m_debugged_process_sp)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s no debugged process shared pointer", __FUNCTION__);
+ return SendErrorResponse (0x36);
+ }
+
+ // Pull out the signal number.
+ packet.SetFilePos (::strlen ("C"));
+ if (packet.GetBytesLeft () < 1)
+ {
+ // Shouldn't be using a C without a signal.
+ return SendIllFormedResponse (packet, "C packet specified without signal.");
+ }
+ const uint32_t signo = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
+ if (signo == std::numeric_limits<uint32_t>::max ())
+ return SendIllFormedResponse (packet, "failed to parse signal number");
+
+ // Handle optional continue address.
+ if (packet.GetBytesLeft () > 0)
+ {
+ // FIXME add continue at address support for $C{signo}[;{continue-address}].
+ if (*packet.Peek () == ';')
+ return SendUnimplementedResponse (packet.GetStringRef().c_str());
+ else
+ return SendIllFormedResponse (packet, "unexpected content after $C{signal-number}");
+ }
+
+ lldb_private::ResumeActionList resume_actions (StateType::eStateRunning, 0);
+ Error error;
+
+ // We have two branches: what to do if a continue thread is specified (in which case we target
+ // sending the signal to that thread), or when we don't have a continue thread set (in which
+ // case we send a signal to the process).
+
+ // TODO discuss with Greg Clayton, make sure this makes sense.
+
+ lldb::tid_t signal_tid = GetContinueThreadID ();
+ if (signal_tid != LLDB_INVALID_THREAD_ID)
+ {
+ // The resume action for the continue thread (or all threads if a continue thread is not set).
+ lldb_private::ResumeAction action = { GetContinueThreadID (), StateType::eStateRunning, static_cast<int> (signo) };
+
+ // Add the action for the continue thread (or all threads when the continue thread isn't present).
+ resume_actions.Append (action);
+ }
+ else
+ {
+ // Send the signal to the process since we weren't targeting a specific continue thread with the signal.
+ error = m_debugged_process_sp->Signal (signo);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed to send signal for process %" PRIu64 ": %s",
+ __FUNCTION__,
+ m_debugged_process_sp->GetID (),
+ error.AsCString ());
+
+ return SendErrorResponse (0x52);
+ }
+ }
+
+ // Resume the threads.
+ error = m_debugged_process_sp->Resume (resume_actions);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed to resume threads for process %" PRIu64 ": %s",
+ __FUNCTION__,
+ m_debugged_process_sp->GetID (),
+ error.AsCString ());
+
+ return SendErrorResponse (0x38);
+ }
+
+ // Don't send an "OK" packet; response is the stopped/exited message.
+ return PacketResult::Success;
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_c (StringExtractorGDBRemote &packet, bool skip_file_pos_adjustment)
+{
+ if (!IsGdbServer ())
+ return SendUnimplementedResponse (packet.GetStringRef().c_str());
+
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s called", __FUNCTION__);
+
+ // We reuse this method in vCont - don't double adjust the file position.
+ if (!skip_file_pos_adjustment)
+ packet.SetFilePos (::strlen ("c"));
+
+ // For now just support all continue.
+ const bool has_continue_address = (packet.GetBytesLeft () > 0);
+ if (has_continue_address)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s not implemented for c{address} variant [%s remains]", __FUNCTION__, packet.Peek ());
+ return SendUnimplementedResponse (packet.GetStringRef().c_str());
+ }
+
+ // Ensure we have a native process.
+ if (!m_debugged_process_sp)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s no debugged process shared pointer", __FUNCTION__);
+ return SendErrorResponse (0x36);
+ }
+
+ // Build the ResumeActionList
+ lldb_private::ResumeActionList actions (StateType::eStateRunning, 0);
+
+ Error error = m_debugged_process_sp->Resume (actions);
+ if (error.Fail ())
+ {
+ if (log)
+ {
+ log->Printf ("GDBRemoteCommunicationServer::%s c failed for process %" PRIu64 ": %s",
+ __FUNCTION__,
+ m_debugged_process_sp->GetID (),
+ error.AsCString ());
+ }
+ return SendErrorResponse (GDBRemoteServerError::eErrorResume);
+ }
+
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s continued process %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID ());
+
+ // No response required from continue.
+ return PacketResult::Success;
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_vCont_actions (StringExtractorGDBRemote &packet)
+{
+ if (!IsGdbServer ())
+ {
+ // only llgs supports $vCont.
+ 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");
+
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_vCont (StringExtractorGDBRemote &packet)
+{
+ if (!IsGdbServer ())
+ {
+ // only llgs supports $vCont
+ return SendUnimplementedResponse (packet.GetStringRef().c_str());
+ }
+
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s handling vCont packet", __FUNCTION__);
+
+ packet.SetFilePos (::strlen ("vCont"));
+
+ // Check if this is all continue (no options or ";c").
+ if (!packet.GetBytesLeft () || (::strcmp (packet.Peek (), ";c") == 0))
+ {
+ // Move the packet past the ";c".
+ if (packet.GetBytesLeft ())
+ packet.SetFilePos (packet.GetFilePos () + ::strlen (";c"));
+
+ const bool skip_file_pos_adjustment = true;
+ return Handle_c (packet, skip_file_pos_adjustment);
+ }
+ else if (::strcmp (packet.Peek (), ";s") == 0)
+ {
+ // Move past the ';', then do a simple 's'.
+ packet.SetFilePos (packet.GetFilePos () + 1);
+ return Handle_s (packet);
+ }
+
+ // Ensure we have a native process.
+ if (!m_debugged_process_sp)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s no debugged process shared pointer", __FUNCTION__);
+ return SendErrorResponse (0x36);
+ }
+
+ ResumeActionList thread_actions;
+
+ while (packet.GetBytesLeft () && *packet.Peek () == ';')
+ {
+ // Skip the semi-colon.
+ packet.GetChar ();
+
+ // Build up the thread action.
+ ResumeAction thread_action;
+ thread_action.tid = LLDB_INVALID_THREAD_ID;
+ thread_action.state = eStateInvalid;
+ thread_action.signal = 0;
+
+ const char action = packet.GetChar ();
+ switch (action)
+ {
+ case 'C':
+ thread_action.signal = packet.GetHexMaxU32 (false, 0);
+ if (thread_action.signal == 0)
+ return SendIllFormedResponse (packet, "Could not parse signal in vCont packet C action");
+ // Fall through to next case...
+
+ case 'c':
+ // Continue
+ thread_action.state = eStateRunning;
+ break;
+
+ case 'S':
+ thread_action.signal = packet.GetHexMaxU32 (false, 0);
+ if (thread_action.signal == 0)
+ return SendIllFormedResponse (packet, "Could not parse signal in vCont packet S action");
+ // Fall through to next case...
+
+ case 's':
+ // Step
+ thread_action.state = eStateStepping;
+ break;
+
+ default:
+ return SendIllFormedResponse (packet, "Unsupported vCont action");
+ break;
+ }
+
+ // Parse out optional :{thread-id} value.
+ if (packet.GetBytesLeft () && (*packet.Peek () == ':'))
+ {
+ // Consume the separator.
+ packet.GetChar ();
+
+ thread_action.tid = packet.GetHexMaxU32 (false, LLDB_INVALID_THREAD_ID);
+ if (thread_action.tid == LLDB_INVALID_THREAD_ID)
+ return SendIllFormedResponse (packet, "Could not parse thread number in vCont packet");
+ }
+
+ thread_actions.Append (thread_action);
+ }
+
+ // If a default action for all other threads wasn't mentioned
+ // then we should stop the threads.
+ thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
+
+ Error error = m_debugged_process_sp->Resume (thread_actions);
+ if (error.Fail ())
+ {
+ if (log)
+ {
+ log->Printf ("GDBRemoteCommunicationServer::%s vCont failed for process %" PRIu64 ": %s",
+ __FUNCTION__,
+ m_debugged_process_sp->GetID (),
+ error.AsCString ());
+ }
+ return SendErrorResponse (GDBRemoteServerError::eErrorResume);
+ }
+
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s continued process %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID ());
+
+ // No response required from vCont.
+ return PacketResult::Success;
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
{
// Send response first before changing m_send_acks to we ack this packet
@@ -1288,7 +2519,7 @@ GDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &
{
std::string path;
packet.GetHexByteString(path);
- Error error = Host::MakeDirectory(path.c_str(),mode);
+ Error error = FileSystem::MakeDirectory(path.c_str(), mode);
if (error.Success())
return SendPacketNoLock ("OK", 2);
else
@@ -1307,7 +2538,7 @@ GDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &
{
std::string path;
packet.GetHexByteString(path);
- Error error = Host::SetFilePermissions (path.c_str(), mode);
+ Error error = FileSystem::SetFilePermissions(path.c_str(), mode);
if (error.Success())
return SendPacketNoLock ("OK", 2);
else
@@ -1457,7 +2688,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packe
packet.GetHexByteString(path);
if (!path.empty())
{
- lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
+ lldb::user_id_t retcode = FileSystem::GetFileSize(FileSpec(path.c_str(), false));
StreamString response;
response.PutChar('F');
response.PutHex64(retcode);
@@ -1498,7 +2729,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &pac
packet.GetHexByteString(path);
if (!path.empty())
{
- bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
+ bool retcode = FileSystem::GetFileExists(FileSpec(path.c_str(), false));
StreamString response;
response.PutChar('F');
response.PutChar(',');
@@ -1519,7 +2750,7 @@ GDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &pa
packet.GetHexByteStringTerminatedBy(dst, ',');
packet.GetChar(); // Skip ',' char
packet.GetHexByteString(src);
- Error error = Host::Symlink(src.c_str(), dst.c_str());
+ Error error = FileSystem::Symlink(src.c_str(), dst.c_str());
StreamString response;
response.Printf("F%u,%u", error.GetError(), error.GetError());
return SendPacketNoLock(response.GetData(), response.GetSize());
@@ -1531,7 +2762,7 @@ GDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &pac
packet.SetFilePos(::strlen("vFile:unlink:"));
std::string path;
packet.GetHexByteString(path);
- Error error = Host::Unlink(path.c_str());
+ Error error = FileSystem::Unlink(path.c_str());
StreamString response;
response.Printf("F%u,%u", error.GetError(), error.GetError());
return SendPacketNoLock(response.GetData(), response.GetSize());
@@ -1579,6 +2810,94 @@ GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &
return SendErrorResponse(24);
}
+void
+GDBRemoteCommunicationServer::SetCurrentThreadID (lldb::tid_t tid)
+{
+ assert (IsGdbServer () && "SetCurrentThreadID() called when not GdbServer code");
+
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s setting current thread id to %" PRIu64, __FUNCTION__, tid);
+
+ m_current_tid = tid;
+ if (m_debugged_process_sp)
+ m_debugged_process_sp->SetCurrentThreadID (m_current_tid);
+}
+
+void
+GDBRemoteCommunicationServer::SetContinueThreadID (lldb::tid_t tid)
+{
+ assert (IsGdbServer () && "SetContinueThreadID() called when not GdbServer code");
+
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s setting continue thread id to %" PRIu64, __FUNCTION__, tid);
+
+ m_continue_tid = tid;
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_stop_reason (StringExtractorGDBRemote &packet)
+{
+ // Handle the $? gdbremote command.
+ if (!IsGdbServer ())
+ return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_stop_reason() unimplemented");
+
+ // If no process, indicate error
+ if (!m_debugged_process_sp)
+ return SendErrorResponse (02);
+
+ return SendStopReasonForState (m_debugged_process_sp->GetState (), true);
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ switch (process_state)
+ {
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateRunning:
+ case eStateStepping:
+ case eStateDetached:
+ // NOTE: gdb protocol doc looks like it should return $OK
+ // when everything is running (i.e. no stopped result).
+ return PacketResult::Success; // Ignore
+
+ case eStateSuspended:
+ case eStateStopped:
+ case eStateCrashed:
+ {
+ lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID ();
+ // Make sure we set the current thread so g and p packets return
+ // the data the gdb will expect.
+ SetCurrentThreadID (tid);
+ return SendStopReplyPacketForThread (tid);
+ }
+
+ case eStateInvalid:
+ case eStateUnloaded:
+ case eStateExited:
+ if (flush_on_exit)
+ FlushInferiorOutput ();
+ return SendWResponse(m_debugged_process_sp.get());
+
+ default:
+ if (log)
+ {
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 ", current state reporting not handled: %s",
+ __FUNCTION__,
+ m_debugged_process_sp->GetID (),
+ StateAsCString (process_state));
+ }
+ break;
+ }
+
+ return SendErrorResponse (0);
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
{
@@ -1595,7 +2914,7 @@ GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet
{
uint64_t a,b;
StreamGDBRemote response;
- if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false)
+ if (FileSystem::CalculateMD5(FileSpec(path.c_str(), false), a, b) == false)
{
response.PutCString("F,");
response.PutCString("x");
@@ -1611,3 +2930,1385 @@ GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet
return SendErrorResponse(25);
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_qRegisterInfo (StringExtractorGDBRemote &packet)
+{
+ // Ensure we're llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_qRegisterInfo() unimplemented");
+
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse (68);
+
+ // Ensure we have a thread.
+ NativeThreadProtocolSP thread_sp (m_debugged_process_sp->GetThreadAtIndex (0));
+ if (!thread_sp)
+ return SendErrorResponse (69);
+
+ // Get the register context for the first thread.
+ NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ());
+ if (!reg_context_sp)
+ return SendErrorResponse (69);
+
+ // Parse out the register number from the request.
+ packet.SetFilePos (strlen("qRegisterInfo"));
+ const uint32_t reg_index = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
+ if (reg_index == std::numeric_limits<uint32_t>::max ())
+ return SendErrorResponse (69);
+
+ // Return the end of registers response if we've iterated one past the end of the register set.
+ if (reg_index >= reg_context_sp->GetRegisterCount ())
+ return SendErrorResponse (69);
+
+ const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index);
+ if (!reg_info)
+ return SendErrorResponse (69);
+
+ // Build the reginfos response.
+ StreamGDBRemote response;
+
+ response.PutCString ("name:");
+ response.PutCString (reg_info->name);
+ response.PutChar (';');
+
+ if (reg_info->alt_name && reg_info->alt_name[0])
+ {
+ response.PutCString ("alt-name:");
+ response.PutCString (reg_info->alt_name);
+ response.PutChar (';');
+ }
+
+ response.Printf ("bitsize:%" PRIu32 ";offset:%" PRIu32 ";", reg_info->byte_size * 8, reg_info->byte_offset);
+
+ switch (reg_info->encoding)
+ {
+ case eEncodingUint: response.PutCString ("encoding:uint;"); break;
+ case eEncodingSint: response.PutCString ("encoding:sint;"); break;
+ case eEncodingIEEE754: response.PutCString ("encoding:ieee754;"); break;
+ case eEncodingVector: response.PutCString ("encoding:vector;"); break;
+ default: break;
+ }
+
+ switch (reg_info->format)
+ {
+ case eFormatBinary: response.PutCString ("format:binary;"); break;
+ case eFormatDecimal: response.PutCString ("format:decimal;"); break;
+ case eFormatHex: response.PutCString ("format:hex;"); break;
+ case eFormatFloat: response.PutCString ("format:float;"); break;
+ case eFormatVectorOfSInt8: response.PutCString ("format:vector-sint8;"); break;
+ case eFormatVectorOfUInt8: response.PutCString ("format:vector-uint8;"); break;
+ case eFormatVectorOfSInt16: response.PutCString ("format:vector-sint16;"); break;
+ case eFormatVectorOfUInt16: response.PutCString ("format:vector-uint16;"); break;
+ case eFormatVectorOfSInt32: response.PutCString ("format:vector-sint32;"); break;
+ case eFormatVectorOfUInt32: response.PutCString ("format:vector-uint32;"); break;
+ case eFormatVectorOfFloat32: response.PutCString ("format:vector-float32;"); break;
+ case eFormatVectorOfUInt128: response.PutCString ("format:vector-uint128;"); break;
+ default: break;
+ };
+
+ const char *const register_set_name = reg_context_sp->GetRegisterSetNameForRegisterAtIndex(reg_index);
+ if (register_set_name)
+ {
+ response.PutCString ("set:");
+ response.PutCString (register_set_name);
+ response.PutChar (';');
+ }
+
+ if (reg_info->kinds[RegisterKind::eRegisterKindGCC] != LLDB_INVALID_REGNUM)
+ response.Printf ("gcc:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindGCC]);
+
+ if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
+ response.Printf ("dwarf:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindDWARF]);
+
+ switch (reg_info->kinds[RegisterKind::eRegisterKindGeneric])
+ {
+ case LLDB_REGNUM_GENERIC_PC: response.PutCString("generic:pc;"); break;
+ case LLDB_REGNUM_GENERIC_SP: response.PutCString("generic:sp;"); break;
+ case LLDB_REGNUM_GENERIC_FP: response.PutCString("generic:fp;"); break;
+ case LLDB_REGNUM_GENERIC_RA: response.PutCString("generic:ra;"); break;
+ case LLDB_REGNUM_GENERIC_FLAGS: response.PutCString("generic:flags;"); break;
+ case LLDB_REGNUM_GENERIC_ARG1: response.PutCString("generic:arg1;"); break;
+ case LLDB_REGNUM_GENERIC_ARG2: response.PutCString("generic:arg2;"); break;
+ case LLDB_REGNUM_GENERIC_ARG3: response.PutCString("generic:arg3;"); break;
+ case LLDB_REGNUM_GENERIC_ARG4: response.PutCString("generic:arg4;"); break;
+ case LLDB_REGNUM_GENERIC_ARG5: response.PutCString("generic:arg5;"); break;
+ case LLDB_REGNUM_GENERIC_ARG6: response.PutCString("generic:arg6;"); break;
+ case LLDB_REGNUM_GENERIC_ARG7: response.PutCString("generic:arg7;"); break;
+ case LLDB_REGNUM_GENERIC_ARG8: response.PutCString("generic:arg8;"); break;
+ default: break;
+ }
+
+ if (reg_info->value_regs && reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
+ {
+ response.PutCString ("container-regs:");
+ int i = 0;
+ for (const uint32_t *reg_num = reg_info->value_regs; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i)
+ {
+ if (i > 0)
+ response.PutChar (',');
+ response.Printf ("%" PRIx32, *reg_num);
+ }
+ response.PutChar (';');
+ }
+
+ if (reg_info->invalidate_regs && reg_info->invalidate_regs[0])
+ {
+ response.PutCString ("invalidate-regs:");
+ int i = 0;
+ for (const uint32_t *reg_num = reg_info->invalidate_regs; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i)
+ {
+ if (i > 0)
+ response.PutChar (',');
+ response.Printf ("%" PRIx32, *reg_num);
+ }
+ response.PutChar (';');
+ }
+
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_qfThreadInfo (StringExtractorGDBRemote &packet)
+{
+ // Ensure we're llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_qfThreadInfo() unimplemented");
+
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // 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() no process (%s), returning OK", __FUNCTION__, m_debugged_process_sp ? "invalid process id" : "null m_debugged_process_sp");
+ return SendOKResponse ();
+ }
+
+ StreamGDBRemote response;
+ response.PutChar ('m');
+
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s() starting thread iteration", __FUNCTION__);
+
+ NativeThreadProtocolSP thread_sp;
+ uint32_t thread_index;
+ for (thread_index = 0, thread_sp = m_debugged_process_sp->GetThreadAtIndex (thread_index);
+ thread_sp;
+ ++thread_index, thread_sp = m_debugged_process_sp->GetThreadAtIndex (thread_index))
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s() iterated thread %" PRIu32 "(%s, tid=0x%" PRIx64 ")", __FUNCTION__, thread_index, thread_sp ? "is not null" : "null", thread_sp ? thread_sp->GetID () : LLDB_INVALID_THREAD_ID);
+ if (thread_index > 0)
+ response.PutChar(',');
+ response.Printf ("%" PRIx64, thread_sp->GetID ());
+ }
+
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s() finished thread iteration", __FUNCTION__);
+
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_qsThreadInfo (StringExtractorGDBRemote &packet)
+{
+ // Ensure we're llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse ("GDBRemoteCommunicationServer::Handle_qsThreadInfo() unimplemented");
+
+ // FIXME for now we return the full thread list in the initial packet and always do nothing here.
+ return SendPacketNoLock ("l", 1);
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_p (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // Ensure we're llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse ("GDBRemoteCommunicationServer::Handle_p() unimplemented");
+
+ // Parse out the register number from the request.
+ packet.SetFilePos (strlen("p"));
+ const uint32_t reg_index = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
+ if (reg_index == std::numeric_limits<uint32_t>::max ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, could not parse register number from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ());
+ return SendErrorResponse (0x15);
+ }
+
+ // Get the thread to use.
+ NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet);
+ if (!thread_sp)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, no thread available", __FUNCTION__);
+ return SendErrorResponse (0x15);
+ }
+
+ // Get the thread's register context.
+ NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ());
+ if (!reg_context_sp)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID (), thread_sp->GetID ());
+ return SendErrorResponse (0x15);
+ }
+
+ // Return the end of registers response if we've iterated one past the end of the register set.
+ if (reg_index >= reg_context_sp->GetRegisterCount ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetRegisterCount ());
+ return SendErrorResponse (0x15);
+ }
+
+ const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index);
+ if (!reg_info)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " returned NULL", __FUNCTION__, reg_index);
+ return SendErrorResponse (0x15);
+ }
+
+ // Build the reginfos response.
+ StreamGDBRemote response;
+
+ // Retrieve the value
+ RegisterValue reg_value;
+ Error error = reg_context_sp->ReadRegister (reg_info, reg_value);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, read of requested register %" PRIu32 " (%s) failed: %s", __FUNCTION__, reg_index, reg_info->name, error.AsCString ());
+ return SendErrorResponse (0x15);
+ }
+
+ const uint8_t *const data = reinterpret_cast<const uint8_t*> (reg_value.GetBytes ());
+ if (!data)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed to get data bytes from requested register %" PRIu32, __FUNCTION__, reg_index);
+ return SendErrorResponse (0x15);
+ }
+
+ // FIXME flip as needed to get data in big/little endian format for this host.
+ for (uint32_t i = 0; i < reg_value.GetByteSize (); ++i)
+ response.PutHex8 (data[i]);
+
+ return SendPacketNoLock (response.GetData (), response.GetSize ());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // Ensure we're llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse ("GDBRemoteCommunicationServer::Handle_P() unimplemented");
+
+ // Ensure there is more content.
+ if (packet.GetBytesLeft () < 1)
+ return SendIllFormedResponse (packet, "Empty P packet");
+
+ // Parse out the register number from the request.
+ packet.SetFilePos (strlen("P"));
+ const uint32_t reg_index = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
+ if (reg_index == std::numeric_limits<uint32_t>::max ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, could not parse register number from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ());
+ return SendErrorResponse (0x29);
+ }
+
+ // Note debugserver would send an E30 here.
+ if ((packet.GetBytesLeft () < 1) || (packet.GetChar () != '='))
+ return SendIllFormedResponse (packet, "P packet missing '=' char after register number");
+
+ // Get process architecture.
+ ArchSpec process_arch;
+ if (!m_debugged_process_sp || !m_debugged_process_sp->GetArchitecture (process_arch))
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed to retrieve inferior architecture", __FUNCTION__);
+ return SendErrorResponse (0x49);
+ }
+
+ // Parse out the value.
+ const uint64_t raw_value = packet.GetHexMaxU64 (process_arch.GetByteOrder () == lldb::eByteOrderLittle, std::numeric_limits<uint64_t>::max ());
+
+ // Get the thread to use.
+ NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet);
+ if (!thread_sp)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, no thread available (thread index 0)", __FUNCTION__);
+ return SendErrorResponse (0x28);
+ }
+
+ // Get the thread's register context.
+ NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ());
+ if (!reg_context_sp)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID (), thread_sp->GetID ());
+ return SendErrorResponse (0x15);
+ }
+
+ const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index);
+ if (!reg_info)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " returned NULL", __FUNCTION__, reg_index);
+ return SendErrorResponse (0x48);
+ }
+
+ // Return the end of registers response if we've iterated one past the end of the register set.
+ if (reg_index >= reg_context_sp->GetRegisterCount ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetRegisterCount ());
+ return SendErrorResponse (0x47);
+ }
+
+
+ // Build the reginfos response.
+ StreamGDBRemote response;
+
+ // FIXME Could be suffixed with a thread: parameter.
+ // That thread then needs to be fed back into the reg context retrieval above.
+ Error error = reg_context_sp->WriteRegisterFromUnsigned (reg_info, raw_value);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, write of requested register %" PRIu32 " (%s) failed: %s", __FUNCTION__, reg_index, reg_info->name, error.AsCString ());
+ return SendErrorResponse (0x32);
+ }
+
+ return SendOKResponse();
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_H (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // Ensure we're llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_H() unimplemented");
+
+ // 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);
+ }
+
+ // Parse out which variant of $H is requested.
+ packet.SetFilePos (strlen("H"));
+ if (packet.GetBytesLeft () < 1)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, H command missing {g,c} variant", __FUNCTION__);
+ return SendIllFormedResponse (packet, "H command missing {g,c} variant");
+ }
+
+ const char h_variant = packet.GetChar ();
+ switch (h_variant)
+ {
+ case 'g':
+ break;
+
+ case 'c':
+ break;
+
+ default:
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, invalid $H variant %c", __FUNCTION__, h_variant);
+ return SendIllFormedResponse (packet, "H variant unsupported, should be c or g");
+ }
+
+ // Parse out the thread number.
+ // FIXME return a parse success/fail value. All values are valid here.
+ const lldb::tid_t tid = packet.GetHexMaxU64 (false, std::numeric_limits<lldb::tid_t>::max ());
+
+ // Ensure we have the given thread when not specifying -1 (all threads) or 0 (any thread).
+ if (tid != LLDB_INVALID_THREAD_ID && tid != 0)
+ {
+ NativeThreadProtocolSP thread_sp (m_debugged_process_sp->GetThreadByID (tid));
+ if (!thread_sp)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, tid %" PRIu64 " not found", __FUNCTION__, tid);
+ return SendErrorResponse (0x15);
+ }
+ }
+
+ // Now switch the given thread type.
+ switch (h_variant)
+ {
+ case 'g':
+ SetCurrentThreadID (tid);
+ break;
+
+ case 'c':
+ SetContinueThreadID (tid);
+ break;
+
+ default:
+ assert (false && "unsupported $H variant - shouldn't get here");
+ return SendIllFormedResponse (packet, "H variant unsupported, should be c or g");
+ }
+
+ return SendOKResponse();
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_interrupt (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+
+ // Ensure we're llgs.
+ if (!IsGdbServer())
+ {
+ // Only supported on llgs
+ return SendUnimplementedResponse ("");
+ }
+
+ // 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);
+ }
+
+ // Build the ResumeActionList - stop everything.
+ lldb_private::ResumeActionList actions (StateType::eStateStopped, 0);
+
+ Error error = m_debugged_process_sp->Resume (actions);
+ if (error.Fail ())
+ {
+ if (log)
+ {
+ log->Printf ("GDBRemoteCommunicationServer::%s failed for process %" PRIu64 ": %s",
+ __FUNCTION__,
+ m_debugged_process_sp->GetID (),
+ error.AsCString ());
+ }
+ return SendErrorResponse (GDBRemoteServerError::eErrorResume);
+ }
+
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s stopped process %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID ());
+
+ // No response required from stop all.
+ return PacketResult::Success;
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_m (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Ensure we're llgs.
+ if (!IsGdbServer())
+ {
+ // Only supported on llgs
+ return SendUnimplementedResponse ("");
+ }
+
+ 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);
+ }
+
+ // Parse out the memory address.
+ packet.SetFilePos (strlen("m"));
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Too short m packet");
+
+ // Read the address. Punting on validation.
+ // FIXME replace with Hex U64 read with no default value that fails on failed read.
+ const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);
+
+ // Validate comma.
+ if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
+ return SendIllFormedResponse(packet, "Comma sep missing in m packet");
+
+ // Get # bytes to read.
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Length missing in m packet");
+
+ const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
+ if (byte_count == 0)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s nothing to read: zero-length packet", __FUNCTION__);
+ return PacketResult::Success;
+ }
+
+ // Allocate the response buffer.
+ std::string buf(byte_count, '\0');
+ if (buf.empty())
+ return SendErrorResponse (0x78);
+
+
+ // Retrieve the process memory.
+ lldb::addr_t bytes_read = 0;
+ lldb_private::Error error = m_debugged_process_sp->ReadMemory (read_addr, &buf[0], byte_count, bytes_read);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " mem 0x%" PRIx64 ": failed to read. Error: %s", __FUNCTION__, m_debugged_process_sp->GetID (), read_addr, error.AsCString ());
+ return SendErrorResponse (0x08);
+ }
+
+ if (bytes_read == 0)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " mem 0x%" PRIx64 ": read %" PRIu64 " of %" PRIu64 " requested bytes", __FUNCTION__, m_debugged_process_sp->GetID (), read_addr, bytes_read, byte_count);
+ return SendErrorResponse (0x08);
+ }
+
+ StreamGDBRemote response;
+ for (lldb::addr_t i = 0; i < bytes_read; ++i)
+ response.PutHex8(buf[i]);
+
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_QSetDetachOnError (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("QSetDetachOnError:"));
+ if (packet.GetU32(0))
+ m_process_launch_info.GetFlags().Set (eLaunchFlagDetachOnError);
+ else
+ m_process_launch_info.GetFlags().Clear (eLaunchFlagDetachOnError);
+ return SendOKResponse ();
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_M (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Ensure we're llgs.
+ if (!IsGdbServer())
+ {
+ // Only supported on llgs
+ return SendUnimplementedResponse ("");
+ }
+
+ 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);
+ }
+
+ // Parse out the memory address.
+ packet.SetFilePos (strlen("M"));
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Too short M packet");
+
+ // Read the address. Punting on validation.
+ // FIXME replace with Hex U64 read with no default value that fails on failed read.
+ const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0);
+
+ // Validate comma.
+ if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
+ return SendIllFormedResponse(packet, "Comma sep missing in M packet");
+
+ // Get # bytes to read.
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Length missing in M packet");
+
+ const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
+ if (byte_count == 0)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s nothing to write: zero-length packet", __FUNCTION__);
+ return PacketResult::Success;
+ }
+
+ // Validate colon.
+ if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':'))
+ return SendIllFormedResponse(packet, "Comma sep missing in M packet after byte length");
+
+ // Allocate the conversion buffer.
+ std::vector<uint8_t> buf(byte_count, 0);
+ if (buf.empty())
+ return SendErrorResponse (0x78);
+
+ // Convert the hex memory write contents to bytes.
+ StreamGDBRemote response;
+ const uint64_t convert_count = static_cast<uint64_t> (packet.GetHexBytes (&buf[0], byte_count, 0));
+ if (convert_count != byte_count)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " mem 0x%" PRIx64 ": asked to write %" PRIu64 " bytes, but only found %" PRIu64 " to convert.", __FUNCTION__, m_debugged_process_sp->GetID (), write_addr, byte_count, convert_count);
+ return SendIllFormedResponse (packet, "M content byte length specified did not match hex-encoded content length");
+ }
+
+ // Write the process memory.
+ lldb::addr_t bytes_written = 0;
+ lldb_private::Error error = m_debugged_process_sp->WriteMemory (write_addr, &buf[0], byte_count, bytes_written);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " mem 0x%" PRIx64 ": failed to write. Error: %s", __FUNCTION__, m_debugged_process_sp->GetID (), write_addr, error.AsCString ());
+ return SendErrorResponse (0x09);
+ }
+
+ if (bytes_written == 0)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " mem 0x%" PRIx64 ": wrote %" PRIu64 " of %" PRIu64 " requested bytes", __FUNCTION__, m_debugged_process_sp->GetID (), write_addr, bytes_written, byte_count);
+ return SendErrorResponse (0x09);
+ }
+
+ return SendOKResponse ();
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_qMemoryRegionInfoSupported (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // We don't support if we're not llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse ("");
+
+ // Currently only the NativeProcessProtocol knows if it can handle a qMemoryRegionInfoSupported
+ // request, but we're not guaranteed to be attached to a process. For now we'll assume the
+ // client only asks this when a process is being debugged.
+
+ // Ensure we have a process running; otherwise, we can't figure this out
+ // since we won't have a NativeProcessProtocol.
+ 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);
+ }
+
+ // Test if we can get any region back when asking for the region around NULL.
+ MemoryRegionInfo region_info;
+ const Error error = m_debugged_process_sp->GetMemoryRegionInfo (0, region_info);
+ if (error.Fail ())
+ {
+ // We don't support memory region info collection for this NativeProcessProtocol.
+ return SendUnimplementedResponse ("");
+ }
+
+ return SendOKResponse();
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_qMemoryRegionInfo (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // We don't support if we're not llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse ("");
+
+ // Ensure we have a 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);
+ }
+
+ // Parse out the memory address.
+ packet.SetFilePos (strlen("qMemoryRegionInfo:"));
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet");
+
+ // Read the address. Punting on validation.
+ const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);
+
+ StreamGDBRemote response;
+
+ // Get the memory region info for the target address.
+ MemoryRegionInfo region_info;
+ const Error error = m_debugged_process_sp->GetMemoryRegionInfo (read_addr, region_info);
+ if (error.Fail ())
+ {
+ // Return the error message.
+
+ response.PutCString ("error:");
+ response.PutCStringAsRawHex8 (error.AsCString ());
+ response.PutChar (';');
+ }
+ else
+ {
+ // Range start and size.
+ response.Printf ("start:%" PRIx64 ";size:%" PRIx64 ";", region_info.GetRange ().GetRangeBase (), region_info.GetRange ().GetByteSize ());
+
+ // Permissions.
+ if (region_info.GetReadable () ||
+ region_info.GetWritable () ||
+ region_info.GetExecutable ())
+ {
+ // Write permissions info.
+ response.PutCString ("permissions:");
+
+ if (region_info.GetReadable ())
+ response.PutChar ('r');
+ if (region_info.GetWritable ())
+ response.PutChar('w');
+ if (region_info.GetExecutable())
+ response.PutChar ('x');
+
+ response.PutChar (';');
+ }
+ }
+
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+
+ // We don't support if we're not llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse ("");
+
+ // Ensure we have a 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);
+ }
+
+ // Parse out software or hardware breakpoint requested.
+ packet.SetFilePos (strlen("Z"));
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Too short Z packet, missing software/hardware specifier");
+
+ bool want_breakpoint = true;
+ bool want_hardware = false;
+
+ const char breakpoint_type_char = packet.GetChar ();
+ switch (breakpoint_type_char)
+ {
+ case '0': want_hardware = false; want_breakpoint = true; break;
+ case '1': want_hardware = true; want_breakpoint = true; break;
+ case '2': want_breakpoint = false; break;
+ case '3': want_breakpoint = false; break;
+ default:
+ return SendIllFormedResponse(packet, "Z packet had invalid software/hardware specifier");
+
+ }
+
+ if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',')
+ return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after breakpoint type");
+
+ // FIXME implement watchpoint support.
+ if (!want_breakpoint)
+ return SendUnimplementedResponse ("watchpoint support not yet implemented");
+
+ // Parse out the breakpoint address.
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Too short Z packet, missing address");
+ const lldb::addr_t breakpoint_addr = packet.GetHexMaxU64(false, 0);
+
+ if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',')
+ return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after address");
+
+ // Parse out the breakpoint kind (i.e. size hint for opcode size).
+ const uint32_t kind = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
+ if (kind == std::numeric_limits<uint32_t>::max ())
+ return SendIllFormedResponse(packet, "Malformed Z packet, failed to parse kind argument");
+
+ if (want_breakpoint)
+ {
+ // Try to set the breakpoint.
+ const Error error = m_debugged_process_sp->SetBreakpoint (breakpoint_addr, kind, want_hardware);
+ if (error.Success ())
+ return SendOKResponse ();
+ else
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " failed to set breakpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ());
+ return SendErrorResponse (0x09);
+ }
+ }
+
+ // FIXME fix up after watchpoints are handled.
+ return SendUnimplementedResponse ("");
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+
+ // We don't support if we're not llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse ("");
+
+ // Ensure we have a 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);
+ }
+
+ // Parse out software or hardware breakpoint requested.
+ packet.SetFilePos (strlen("Z"));
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Too short z packet, missing software/hardware specifier");
+
+ bool want_breakpoint = true;
+
+ const char breakpoint_type_char = packet.GetChar ();
+ switch (breakpoint_type_char)
+ {
+ case '0': want_breakpoint = true; break;
+ case '1': want_breakpoint = true; break;
+ case '2': want_breakpoint = false; break;
+ case '3': want_breakpoint = false; break;
+ default:
+ return SendIllFormedResponse(packet, "z packet had invalid software/hardware specifier");
+
+ }
+
+ if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',')
+ return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after breakpoint type");
+
+ // FIXME implement watchpoint support.
+ if (!want_breakpoint)
+ return SendUnimplementedResponse ("watchpoint support not yet implemented");
+
+ // Parse out the breakpoint address.
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Too short z packet, missing address");
+ const lldb::addr_t breakpoint_addr = packet.GetHexMaxU64(false, 0);
+
+ if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',')
+ return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after address");
+
+ // Parse out the breakpoint kind (i.e. size hint for opcode size).
+ const uint32_t kind = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
+ if (kind == std::numeric_limits<uint32_t>::max ())
+ return SendIllFormedResponse(packet, "Malformed z packet, failed to parse kind argument");
+
+ if (want_breakpoint)
+ {
+ // Try to set the breakpoint.
+ const Error error = m_debugged_process_sp->RemoveBreakpoint (breakpoint_addr);
+ if (error.Success ())
+ return SendOKResponse ();
+ else
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " failed to remove breakpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ());
+ return SendErrorResponse (0x09);
+ }
+ }
+
+ // FIXME fix up after watchpoints are handled.
+ return SendUnimplementedResponse ("");
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_s (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_THREAD));
+
+ // We don't support if we're not llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse ("");
+
+ // Ensure we have a 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 (0x32);
+ }
+
+ // We first try to use a continue thread id. If any one or any all set, use the current thread.
+ // Bail out if we don't have a thread id.
+ lldb::tid_t tid = GetContinueThreadID ();
+ if (tid == 0 || tid == LLDB_INVALID_THREAD_ID)
+ tid = GetCurrentThreadID ();
+ if (tid == LLDB_INVALID_THREAD_ID)
+ return SendErrorResponse (0x33);
+
+ // Double check that we have such a thread.
+ // TODO investigate: on MacOSX we might need to do an UpdateThreads () here.
+ NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetThreadByID (tid);
+ if (!thread_sp || thread_sp->GetID () != tid)
+ return SendErrorResponse (0x33);
+
+ // Create the step action for the given thread.
+ lldb_private::ResumeAction action = { tid, eStateStepping, 0 };
+
+ // Setup the actions list.
+ lldb_private::ResumeActionList actions;
+ actions.Append (action);
+
+ // All other threads stop while we're single stepping a thread.
+ actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
+ Error error = m_debugged_process_sp->Resume (actions);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " tid %" PRIu64 " Resume() failed with error: %s", __FUNCTION__, m_debugged_process_sp->GetID (), tid, error.AsCString ());
+ return SendErrorResponse(0x49);
+ }
+
+ // No response here - the stop or exit will come from the resulting action.
+ return PacketResult::Success;
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_qSupported (StringExtractorGDBRemote &packet)
+{
+ StreamGDBRemote response;
+
+ // Features common to lldb-platform and llgs.
+ uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet size--debugger can always use less
+ response.Printf ("PacketSize=%x", max_packet_size);
+
+ response.PutCString (";QStartNoAckMode+");
+ response.PutCString (";QThreadSuffixSupported+");
+ response.PutCString (";QListThreadsInStopReply+");
+#if defined(__linux__)
+ response.PutCString (";qXfer:auxv:read+");
+#endif
+
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_QThreadSuffixSupported (StringExtractorGDBRemote &packet)
+{
+ m_thread_suffix_supported = true;
+ return SendOKResponse();
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_QListThreadsInStopReply (StringExtractorGDBRemote &packet)
+{
+ m_list_threads_in_stop_reply = true;
+ return SendOKResponse();
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_qXfer_auxv_read (StringExtractorGDBRemote &packet)
+{
+ // We don't support if we're not llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse ("only supported for lldb-gdbserver");
+
+ // *BSD impls should be able to do this too.
+#if defined(__linux__)
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Parse out the offset.
+ packet.SetFilePos (strlen("qXfer:auxv:read::"));
+ if (packet.GetBytesLeft () < 1)
+ return SendIllFormedResponse (packet, "qXfer:auxv:read:: packet missing offset");
+
+ const uint64_t auxv_offset = packet.GetHexMaxU64 (false, std::numeric_limits<uint64_t>::max ());
+ if (auxv_offset == std::numeric_limits<uint64_t>::max ())
+ return SendIllFormedResponse (packet, "qXfer:auxv:read:: packet missing offset");
+
+ // Parse out comma.
+ if (packet.GetBytesLeft () < 1 || packet.GetChar () != ',')
+ return SendIllFormedResponse (packet, "qXfer:auxv:read:: packet missing comma after offset");
+
+ // Parse out the length.
+ const uint64_t auxv_length = packet.GetHexMaxU64 (false, std::numeric_limits<uint64_t>::max ());
+ if (auxv_length == std::numeric_limits<uint64_t>::max ())
+ return SendIllFormedResponse (packet, "qXfer:auxv:read:: packet missing length");
+
+ // Grab the auxv data if we need it.
+ if (!m_active_auxv_buffer_sp)
+ {
+ // Make sure we have a valid 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 (0x10);
+ }
+
+ // Grab the auxv data.
+ m_active_auxv_buffer_sp = Host::GetAuxvData (m_debugged_process_sp->GetID ());
+ if (!m_active_auxv_buffer_sp || m_active_auxv_buffer_sp->GetByteSize () == 0)
+ {
+ // Hmm, no auxv data, call that an error.
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, no auxv data retrieved", __FUNCTION__);
+ m_active_auxv_buffer_sp.reset ();
+ return SendErrorResponse (0x11);
+ }
+ }
+
+ // FIXME find out if/how I lock the stream here.
+
+ StreamGDBRemote response;
+ bool done_with_buffer = false;
+
+ if (auxv_offset >= m_active_auxv_buffer_sp->GetByteSize ())
+ {
+ // We have nothing left to send. Mark the buffer as complete.
+ response.PutChar ('l');
+ done_with_buffer = true;
+ }
+ else
+ {
+ // Figure out how many bytes are available starting at the given offset.
+ const uint64_t bytes_remaining = m_active_auxv_buffer_sp->GetByteSize () - auxv_offset;
+
+ // Figure out how many bytes we're going to read.
+ const uint64_t bytes_to_read = (auxv_length > bytes_remaining) ? bytes_remaining : auxv_length;
+
+ // Mark the response type according to whether we're reading the remainder of the auxv data.
+ if (bytes_to_read >= bytes_remaining)
+ {
+ // There will be nothing left to read after this
+ response.PutChar ('l');
+ done_with_buffer = true;
+ }
+ else
+ {
+ // There will still be bytes to read after this request.
+ response.PutChar ('m');
+ }
+
+ // Now write the data in encoded binary form.
+ response.PutEscapedBytes (m_active_auxv_buffer_sp->GetBytes () + auxv_offset, bytes_to_read);
+ }
+
+ if (done_with_buffer)
+ m_active_auxv_buffer_sp.reset ();
+
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+#else
+ return SendUnimplementedResponse ("not implemented on this platform");
+#endif
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_QSaveRegisterState (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");
+
+ // Move past packet name.
+ packet.SetFilePos (strlen ("QSaveRegisterState"));
+
+ // Get the thread to use.
+ NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet);
+ if (!thread_sp)
+ {
+ if (m_thread_suffix_supported)
+ return SendIllFormedResponse (packet, "No thread specified in QSaveRegisterState packet");
+ else
+ return SendIllFormedResponse (packet, "No thread was is set with the Hg packet");
+ }
+
+ // Grab the register context for the thread.
+ NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ());
+ if (!reg_context_sp)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID (), thread_sp->GetID ());
+ return SendErrorResponse (0x15);
+ }
+
+ // Save registers to a buffer.
+ DataBufferSP register_data_sp;
+ Error error = reg_context_sp->ReadAllRegisterValues (register_data_sp);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " failed to save all register values: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ());
+ return SendErrorResponse (0x75);
+ }
+
+ // Allocate a new save id.
+ const uint32_t save_id = GetNextSavedRegistersID ();
+ assert ((m_saved_registers_map.find (save_id) == m_saved_registers_map.end ()) && "GetNextRegisterSaveID() returned an existing register save id");
+
+ // Save the register data buffer under the save id.
+ {
+ Mutex::Locker locker (m_saved_registers_mutex);
+ m_saved_registers_map[save_id] = register_data_sp;
+ }
+
+ // Write the response.
+ StreamGDBRemote response;
+ response.Printf ("%" PRIu32, save_id);
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_QRestoreRegisterState (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");
+
+ // Parse out save id.
+ packet.SetFilePos (strlen ("QRestoreRegisterState:"));
+ if (packet.GetBytesLeft () < 1)
+ return SendIllFormedResponse (packet, "QRestoreRegisterState packet missing register save id");
+
+ const uint32_t save_id = packet.GetU32 (0);
+ if (save_id == 0)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s QRestoreRegisterState packet has malformed save id, expecting decimal uint32_t", __FUNCTION__);
+ return SendErrorResponse (0x76);
+ }
+
+ // Get the thread to use.
+ NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet);
+ if (!thread_sp)
+ {
+ if (m_thread_suffix_supported)
+ return SendIllFormedResponse (packet, "No thread specified in QRestoreRegisterState packet");
+ else
+ return SendIllFormedResponse (packet, "No thread was is set with the Hg packet");
+ }
+
+ // Grab the register context for the thread.
+ NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ());
+ if (!reg_context_sp)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID (), thread_sp->GetID ());
+ return SendErrorResponse (0x15);
+ }
+
+ // Retrieve register state buffer, then remove from the list.
+ DataBufferSP register_data_sp;
+ {
+ Mutex::Locker locker (m_saved_registers_mutex);
+
+ // Find the register set buffer for the given save id.
+ auto it = m_saved_registers_map.find (save_id);
+ if (it == m_saved_registers_map.end ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " does not have a register set save buffer for id %" PRIu32, __FUNCTION__, m_debugged_process_sp->GetID (), save_id);
+ return SendErrorResponse (0x77);
+ }
+ register_data_sp = it->second;
+
+ // Remove it from the map.
+ m_saved_registers_map.erase (it);
+ }
+
+ Error error = reg_context_sp->WriteAllRegisterValues (register_data_sp);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " failed to restore all register values: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ());
+ return SendErrorResponse (0x77);
+ }
+
+ return SendOKResponse();
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_vAttach (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");
+
+ // Consume the ';' after vAttach.
+ packet.SetFilePos (strlen ("vAttach"));
+ if (!packet.GetBytesLeft () || packet.GetChar () != ';')
+ return SendIllFormedResponse (packet, "vAttach missing expected ';'");
+
+ // Grab the PID to which we will attach (assume hex encoding).
+ lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID, 16);
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return SendIllFormedResponse (packet, "vAttach failed to parse the process id");
+
+ // Attempt to attach.
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s attempting to attach to pid %" PRIu64, __FUNCTION__, pid);
+
+ Error error = AttachToProcess (pid);
+
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed to attach to pid %" PRIu64 ": %s\n", __FUNCTION__, pid, error.AsCString());
+ return SendErrorResponse (0x01);
+ }
+
+ // Notify we attached by sending a stop packet.
+ return SendStopReasonForState (m_debugged_process_sp->GetState (), true);
+
+ return PacketResult::Success;
+}
+
+void
+GDBRemoteCommunicationServer::FlushInferiorOutput ()
+{
+ // If we're not monitoring an inferior's terminal, ignore this.
+ if (!m_stdio_communication.IsConnected())
+ return;
+
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s() called", __FUNCTION__);
+
+ // FIXME implement a timeout on the join.
+ m_stdio_communication.JoinReadThread();
+}
+
+void
+GDBRemoteCommunicationServer::MaybeCloseInferiorTerminalConnection ()
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Tell the stdio connection to shut down.
+ if (m_stdio_communication.IsConnected())
+ {
+ auto connection = m_stdio_communication.GetConnection();
+ if (connection)
+ {
+ Error error;
+ connection->Disconnect (&error);
+
+ if (error.Success ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s disconnect process terminal stdio - SUCCESS", __FUNCTION__);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s disconnect process terminal stdio - FAIL: %s", __FUNCTION__, error.AsCString ());
+ }
+ }
+ }
+}
+
+
+lldb_private::NativeThreadProtocolSP
+GDBRemoteCommunicationServer::GetThreadFromSuffix (StringExtractorGDBRemote &packet)
+{
+ NativeThreadProtocolSP thread_sp;
+
+ // We have no thread if we don't have a process.
+ if (!m_debugged_process_sp || m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)
+ return thread_sp;
+
+ // If the client hasn't asked for thread suffix support, there will not be a thread suffix.
+ // Use the current thread in that case.
+ if (!m_thread_suffix_supported)
+ {
+ const lldb::tid_t current_tid = GetCurrentThreadID ();
+ if (current_tid == LLDB_INVALID_THREAD_ID)
+ return thread_sp;
+ else if (current_tid == 0)
+ {
+ // Pick a thread.
+ return m_debugged_process_sp->GetThreadAtIndex (0);
+ }
+ else
+ return m_debugged_process_sp->GetThreadByID (current_tid);
+ }
+
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // Parse out the ';'.
+ if (packet.GetBytesLeft () < 1 || packet.GetChar () != ';')
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s gdb-remote parse error: expected ';' prior to start of thread suffix: packet contents = '%s'", __FUNCTION__, packet.GetStringRef ().c_str ());
+ return thread_sp;
+ }
+
+ if (!packet.GetBytesLeft ())
+ return thread_sp;
+
+ // Parse out thread: portion.
+ if (strncmp (packet.Peek (), "thread:", strlen("thread:")) != 0)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s gdb-remote parse error: expected 'thread:' but not found, packet contents = '%s'", __FUNCTION__, packet.GetStringRef ().c_str ());
+ return thread_sp;
+ }
+ packet.SetFilePos (packet.GetFilePos () + strlen("thread:"));
+ const lldb::tid_t tid = packet.GetHexMaxU64(false, 0);
+ if (tid != 0)
+ return m_debugged_process_sp->GetThreadByID (tid);
+
+ return thread_sp;
+}
+
+lldb::tid_t
+GDBRemoteCommunicationServer::GetCurrentThreadID () const
+{
+ if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID)
+ {
+ // Use whatever the debug process says is the current thread id
+ // since the protocol either didn't specify or specified we want
+ // any/all threads marked as the current thread.
+ if (!m_debugged_process_sp)
+ return LLDB_INVALID_THREAD_ID;
+ return m_debugged_process_sp->GetCurrentThreadID ();
+ }
+ // Use the specific current thread id set by the gdb remote protocol.
+ return m_current_tid;
+}
+
+uint32_t
+GDBRemoteCommunicationServer::GetNextSavedRegistersID ()
+{
+ Mutex::Locker locker (m_saved_registers_mutex);
+ return m_next_saved_registers_id++;
+}
+
+void
+GDBRemoteCommunicationServer::ClearProcessSpecificData ()
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s()", __FUNCTION__);
+
+ // Clear any auxv cached data.
+ // *BSD impls should be able to do this too.
+#if defined(__linux__)
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s clearing auxv buffer (previously %s)",
+ __FUNCTION__,
+ m_active_auxv_buffer_sp ? "was set" : "was not set");
+ m_active_auxv_buffer_sp.reset ();
+#endif
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 913c6b673cfb..13c037c0287b 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -14,16 +14,23 @@
// C++ Includes
#include <vector>
#include <set>
+#include <unordered_map>
// Other libraries and framework includes
// Project includes
+#include "lldb/lldb-private-forward.h"
+#include "lldb/Core/Communication.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Target/Process.h"
#include "GDBRemoteCommunication.h"
+#include "../../../Host/common/NativeProcessProtocol.h"
+
class ProcessGDBRemote;
class StringExtractorGDBRemote;
-class GDBRemoteCommunicationServer : public GDBRemoteCommunication
+class GDBRemoteCommunicationServer :
+ public GDBRemoteCommunication,
+ public lldb_private::NativeProcessProtocol::NativeDelegate
{
public:
typedef std::map<uint16_t, lldb::pid_t> PortMap;
@@ -38,12 +45,13 @@ public:
GDBRemoteCommunicationServer(bool is_platform);
GDBRemoteCommunicationServer(bool is_platform,
- const lldb::PlatformSP& platform_sp);
+ const lldb::PlatformSP& platform_sp,
+ lldb::DebuggerSP& debugger_sp);
virtual
~GDBRemoteCommunicationServer();
- bool
+ PacketResult
GetPacketAndSendResponse (uint32_t timeout_usec,
lldb_private::Error &error,
bool &interrupt,
@@ -188,6 +196,31 @@ public:
lldb_private::Error
LaunchProcess ();
+ //------------------------------------------------------------------
+ /// Attach to a process.
+ ///
+ /// This method supports attaching llgs to a process accessible via the
+ /// configured Platform.
+ ///
+ /// @return
+ /// An Error object indicating the success or failure of the
+ /// attach operation.
+ //------------------------------------------------------------------
+ lldb_private::Error
+ AttachToProcess (lldb::pid_t pid);
+
+ //------------------------------------------------------------------
+ // NativeProcessProtocol::NativeDelegate overrides
+ //------------------------------------------------------------------
+ void
+ InitializeDelegate (lldb_private::NativeProcessProtocol *process) override;
+
+ void
+ ProcessStateChanged (lldb_private::NativeProcessProtocol *process, lldb::StateType state) override;
+
+ void
+ DidExec (lldb_private::NativeProcessProtocol *process) override;
+
protected:
lldb::PlatformSP m_platform_sp;
lldb::thread_t m_async_thread;
@@ -199,7 +232,20 @@ protected:
uint32_t m_proc_infos_index;
PortMap m_port_map;
uint16_t m_port_offset;
-
+ lldb::tid_t m_current_tid;
+ lldb::tid_t m_continue_tid;
+ lldb_private::Mutex m_debugged_process_mutex;
+ lldb_private::NativeProcessProtocolSP m_debugged_process_sp;
+ lldb::DebuggerSP m_debugger_sp;
+ Communication m_stdio_communication;
+ bool m_exit_now; // use in asynchronous handling to indicate process should exit.
+ lldb::StateType m_inferior_prev_state;
+ bool m_thread_suffix_supported;
+ bool m_list_threads_in_stop_reply;
+ lldb::DataBufferSP m_active_auxv_buffer_sp;
+ lldb_private::Mutex m_saved_registers_mutex;
+ std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map;
+ uint32_t m_next_saved_registers_id;
PacketResult
SendUnimplementedResponse (const char *packet);
@@ -208,9 +254,24 @@ protected:
SendErrorResponse (uint8_t error);
PacketResult
+ SendIllFormedResponse (const StringExtractorGDBRemote &packet, const char *error_message);
+
+ PacketResult
SendOKResponse ();
PacketResult
+ SendONotification (const char *buffer, uint32_t len);
+
+ PacketResult
+ SendWResponse (lldb_private::NativeProcessProtocol *process);
+
+ PacketResult
+ SendStopReplyPacketForThread (lldb::tid_t tid);
+
+ PacketResult
+ SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit);
+
+ PacketResult
Handle_A (StringExtractorGDBRemote &packet);
PacketResult
@@ -233,7 +294,10 @@ protected:
PacketResult
Handle_qPlatform_chmod (StringExtractorGDBRemote &packet);
-
+
+ PacketResult
+ Handle_qProcessInfo (StringExtractorGDBRemote &packet);
+
PacketResult
Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
@@ -265,6 +329,9 @@ protected:
Handle_QSetDisableASLR (StringExtractorGDBRemote &packet);
PacketResult
+ Handle_QSetDetachOnError (StringExtractorGDBRemote &packet);
+
+ PacketResult
Handle_QSetWorkingDir (StringExtractorGDBRemote &packet);
PacketResult
@@ -281,7 +348,22 @@ protected:
PacketResult
Handle_QSetSTDERR (StringExtractorGDBRemote &packet);
-
+
+ PacketResult
+ Handle_C (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_c (StringExtractorGDBRemote &packet, bool skip_file_pos_adjustment = false);
+
+ PacketResult
+ Handle_vCont (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_vCont_actions (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_stop_reason (StringExtractorGDBRemote &packet);
+
PacketResult
Handle_vFile_Open (StringExtractorGDBRemote &packet);
@@ -318,6 +400,87 @@ protected:
PacketResult
Handle_qPlatform_shell (StringExtractorGDBRemote &packet);
+ PacketResult
+ Handle_qRegisterInfo (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_qfThreadInfo (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_qsThreadInfo (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_p (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_P (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_H (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_interrupt (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_m (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_M (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_qMemoryRegionInfoSupported (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_qMemoryRegionInfo (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_Z (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_z (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_s (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_qSupported (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_QThreadSuffixSupported (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_QListThreadsInStopReply (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_qXfer_auxv_read (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_QSaveRegisterState (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_QRestoreRegisterState (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_vAttach (StringExtractorGDBRemote &packet);
+
+ void
+ SetCurrentThreadID (lldb::tid_t tid);
+
+ lldb::tid_t
+ GetCurrentThreadID () const;
+
+ void
+ SetContinueThreadID (lldb::tid_t tid);
+
+ lldb::tid_t
+ GetContinueThreadID () const { return m_continue_tid; }
+
+ lldb_private::Error
+ SetSTDIOFileDescriptor (int fd);
+
+ static void
+ STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
+
private:
bool
DebugserverProcessReaped (lldb::pid_t pid);
@@ -342,6 +505,41 @@ private:
bool
KillSpawnedProcess (lldb::pid_t pid);
+ bool
+ IsGdbServer ()
+ {
+ return !m_is_platform;
+ }
+
+ /// Launch a process from lldb-gdbserver
+ lldb_private::Error
+ LaunchDebugServerProcess ();
+
+ /// Launch a process from lldb-platform
+ lldb_private::Error
+ LaunchPlatformProcess ();
+
+ void
+ HandleInferiorState_Exited (lldb_private::NativeProcessProtocol *process);
+
+ void
+ HandleInferiorState_Stopped (lldb_private::NativeProcessProtocol *process);
+
+ void
+ FlushInferiorOutput ();
+
+ lldb_private::NativeThreadProtocolSP
+ GetThreadFromSuffix (StringExtractorGDBRemote &packet);
+
+ uint32_t
+ GetNextSavedRegistersID ();
+
+ void
+ MaybeCloseInferiorTerminalConnection ();
+
+ void
+ ClearProcessSpecificData ();
+
//------------------------------------------------------------------
// For GDBRemoteCommunicationServer only
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 73b9b3e8267e..6d7eca1a0ced 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -21,6 +21,7 @@
#include "lldb/Interpreter/PythonDataObjects.h"
#endif
#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/Utils.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
@@ -199,7 +200,7 @@ GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataE
const uint32_t prim_reg = reg_info->value_regs[idx];
if (prim_reg == LLDB_INVALID_REGNUM)
break;
- // We have a valid primordial regsiter as our constituent.
+ // We have a valid primordial register as our constituent.
// Grab the corresponding register info.
const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
if (prim_reg_info == NULL)
@@ -232,11 +233,20 @@ GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataE
if (&data != &m_reg_data)
{
+#if defined (LLDB_CONFIGURATION_DEBUG)
+ assert (m_reg_data.GetByteSize() >= reg_info->byte_offset + reg_info->byte_size);
+#endif
+ // If our register context and our register info disagree, which should never happen, don't
+ // read past the end of the buffer.
+ if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
+ return false;
+
// If we aren't extracting into our own buffer (which
// only happens when this function is called from
// ReadRegisterValue(uint32_t, Scalar&)) then
// we transfer bytes from our buffer into the data
// buffer that was passed in
+
data.SetByteOrder (m_reg_data.GetByteOrder());
data.SetData (m_reg_data, reg_info->byte_offset, reg_info->byte_size);
}
@@ -322,6 +332,16 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const lldb_private::RegisterInfo *
// if (gdb_comm.IsRunning())
// return false;
+
+#if defined (LLDB_CONFIGURATION_DEBUG)
+ assert (m_reg_data.GetByteSize() >= reg_info->byte_offset + reg_info->byte_size);
+#endif
+
+ // If our register context and our register info disagree, which should never happen, don't
+ // overwrite past the end of the buffer.
+ if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
+ return false;
+
// Grab a pointer to where we are going to put this register
uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
@@ -389,7 +409,7 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const lldb_private::RegisterInfo *
const uint32_t reg = reg_info->value_regs[idx];
if (reg == LLDB_INVALID_REGNUM)
break;
- // We have a valid primordial regsiter as our constituent.
+ // We have a valid primordial register as our constituent.
// Grab the corresponding register info.
const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg);
if (value_reg_info == NULL)
@@ -502,6 +522,8 @@ GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
StringExtractorGDBRemote response;
+ const bool use_g_packet = gdb_comm.AvoidGPackets ((ProcessGDBRemote *)process) == false;
+
Mutex::Locker locker;
if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for read all registers."))
{
@@ -519,29 +541,62 @@ GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
packet_len = ::snprintf (packet, sizeof(packet), "g");
assert (packet_len < ((int)sizeof(packet) - 1));
- if (gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success)
+ if (use_g_packet && gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success)
{
- if (response.IsErrorResponse())
- return false;
-
- std::string &response_str = response.GetStringRef();
- if (isxdigit(response_str[0]))
+ int packet_len = 0;
+ if (thread_suffix_supported)
+ packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64, m_thread.GetProtocolID());
+ else
+ packet_len = ::snprintf (packet, sizeof(packet), "g");
+ assert (packet_len < ((int)sizeof(packet) - 1));
+
+ if (gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success)
{
- response_str.insert(0, 1, 'G');
- if (thread_suffix_supported)
+ if (response.IsErrorResponse())
+ return false;
+
+ std::string &response_str = response.GetStringRef();
+ if (isxdigit(response_str[0]))
{
- char thread_id_cstr[64];
- ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
- response_str.append (thread_id_cstr);
+ response_str.insert(0, 1, 'G');
+ if (thread_suffix_supported)
+ {
+ char thread_id_cstr[64];
+ ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
+ response_str.append (thread_id_cstr);
+ }
+ data_sp.reset (new DataBufferHeap (response_str.c_str(), response_str.size()));
+ return true;
}
- data_sp.reset (new DataBufferHeap (response_str.c_str(), response_str.size()));
- return true;
}
}
+ else
+ {
+ // For the use_g_packet == false case, we're going to read each register
+ // individually and store them as binary data in a buffer instead of as ascii
+ // characters.
+ const RegisterInfo *reg_info;
+
+ // data_sp will take ownership of this DataBufferHeap pointer soon.
+ DataBufferSP reg_ctx(new DataBufferHeap(m_reg_info.GetRegisterDataByteSize(), 0));
+
+ for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex (i)) != NULL; i++)
+ {
+ if (reg_info->value_regs) // skip registers that are slices of real registers
+ continue;
+ ReadRegisterBytes (reg_info, m_reg_data);
+ // ReadRegisterBytes saves the contents of the register in to the m_reg_data buffer
+ }
+ memcpy (reg_ctx->GetBytes(), m_reg_data.GetDataStart(), m_reg_info.GetRegisterDataByteSize());
+
+ data_sp = reg_ctx;
+ return true;
+ }
}
}
else
{
+
Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
if (log)
{
@@ -575,6 +630,8 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
+ const bool use_g_packet = gdb_comm.AvoidGPackets ((ProcessGDBRemote *)process) == false;
+
StringExtractorGDBRemote response;
Mutex::Locker locker;
if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for write all registers."))
@@ -588,63 +645,126 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
// as well.
const char *G_packet = (const char *)data_sp->GetBytes();
size_t G_packet_len = data_sp->GetByteSize();
- if (gdb_comm.SendPacketAndWaitForResponse (G_packet,
- G_packet_len,
- response,
- false) == GDBRemoteCommunication::PacketResult::Success)
+ if (use_g_packet
+ && gdb_comm.SendPacketAndWaitForResponse (G_packet,
+ G_packet_len,
+ response,
+ false) == GDBRemoteCommunication::PacketResult::Success)
{
- if (response.IsOKResponse())
- return true;
- else if (response.IsErrorResponse())
+ // The data_sp contains the entire G response packet including the
+ // G, and if the thread suffix is supported, it has the thread suffix
+ // as well.
+ const char *G_packet = (const char *)data_sp->GetBytes();
+ size_t G_packet_len = data_sp->GetByteSize();
+ if (gdb_comm.SendPacketAndWaitForResponse (G_packet,
+ G_packet_len,
+ response,
+ false) == GDBRemoteCommunication::PacketResult::Success)
{
- uint32_t num_restored = 0;
- // We need to manually go through all of the registers and
- // restore them manually
-
- response.GetStringRef().assign (G_packet, G_packet_len);
- response.SetFilePos(1); // Skip the leading 'G'
- DataBufferHeap buffer (m_reg_data.GetByteSize(), 0);
- DataExtractor restore_data (buffer.GetBytes(),
- buffer.GetByteSize(),
- m_reg_data.GetByteOrder(),
- m_reg_data.GetAddressByteSize());
-
- const uint32_t bytes_extracted = response.GetHexBytes ((void *)restore_data.GetDataStart(),
- restore_data.GetByteSize(),
- '\xcc');
-
- if (bytes_extracted < restore_data.GetByteSize())
- restore_data.SetData(restore_data.GetDataStart(), bytes_extracted, m_reg_data.GetByteOrder());
-
- //ReadRegisterBytes (const RegisterInfo *reg_info, RegisterValue &value, DataExtractor &data)
- const RegisterInfo *reg_info;
- // We have to march the offset of each register along in the
- // buffer to make sure we get the right offset.
- uint32_t reg_byte_offset = 0;
- for (uint32_t reg_idx=0; (reg_info = GetRegisterInfoAtIndex (reg_idx)) != NULL; ++reg_idx, reg_byte_offset += reg_info->byte_size)
+ if (response.IsOKResponse())
+ return true;
+ else if (response.IsErrorResponse())
{
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- // Skip composite registers.
- if (reg_info->value_regs)
- continue;
+ uint32_t num_restored = 0;
+ // We need to manually go through all of the registers and
+ // restore them manually
+
+ response.GetStringRef().assign (G_packet, G_packet_len);
+ response.SetFilePos(1); // Skip the leading 'G'
+
+ // G_packet_len is hex-ascii characters plus prefix 'G' plus suffix thread specifier.
+ // This means buffer will be a little more than 2x larger than necessary but we resize
+ // it down once we've extracted all hex ascii chars from the packet.
+ DataBufferHeap buffer (G_packet_len, 0);
+ DataExtractor restore_data (buffer.GetBytes(),
+ buffer.GetByteSize(),
+ m_reg_data.GetByteOrder(),
+ m_reg_data.GetAddressByteSize());
+
+ const uint32_t bytes_extracted = response.GetHexBytes ((void *)restore_data.GetDataStart(),
+ restore_data.GetByteSize(),
+ '\xcc');
+
+ if (bytes_extracted < restore_data.GetByteSize())
+ restore_data.SetData(restore_data.GetDataStart(), bytes_extracted, m_reg_data.GetByteOrder());
+
+ const RegisterInfo *reg_info;
+
+ // The g packet contents may either include the slice registers (registers defined in
+ // terms of other registers, e.g. eax is a subset of rax) or not. The slice registers
+ // should NOT be in the g packet, but some implementations may incorrectly include them.
+ //
+ // If the slice registers are included in the packet, we must step over the slice registers
+ // when parsing the packet -- relying on the RegisterInfo byte_offset field would be incorrect.
+ // If the slice registers are not included, then using the byte_offset values into the
+ // data buffer is the best way to find individual register values.
+
+ uint64_t size_including_slice_registers = 0;
+ uint64_t size_not_including_slice_registers = 0;
+ uint64_t size_by_highest_offset = 0;
+
+ for (uint32_t reg_idx=0; (reg_info = GetRegisterInfoAtIndex (reg_idx)) != NULL; ++reg_idx)
+ {
+ size_including_slice_registers += reg_info->byte_size;
+ if (reg_info->value_regs == NULL)
+ size_not_including_slice_registers += reg_info->byte_size;
+ if (reg_info->byte_offset >= size_by_highest_offset)
+ size_by_highest_offset = reg_info->byte_offset + reg_info->byte_size;
+ }
- // Only write down the registers that need to be written
- // if we are going to be doing registers individually.
- bool write_reg = true;
- const uint32_t reg_byte_size = reg_info->byte_size;
+ bool use_byte_offset_into_buffer;
+ if (size_by_highest_offset == restore_data.GetByteSize())
+ {
+ // The size of the packet agrees with the highest offset: + size in the register file
+ use_byte_offset_into_buffer = true;
+ }
+ else if (size_not_including_slice_registers == restore_data.GetByteSize())
+ {
+ // The size of the packet is the same as concatenating all of the registers sequentially,
+ // skipping the slice registers
+ use_byte_offset_into_buffer = true;
+ }
+ else if (size_including_slice_registers == restore_data.GetByteSize())
+ {
+ // The slice registers are present in the packet (when they shouldn't be).
+ // Don't try to use the RegisterInfo byte_offset into the restore_data, it will
+ // point to the wrong place.
+ use_byte_offset_into_buffer = false;
+ }
+ else {
+ // None of our expected sizes match the actual g packet data we're looking at.
+ // The most conservative approach here is to use the running total byte offset.
+ use_byte_offset_into_buffer = false;
+ }
- const char *restore_src = (const char *)restore_data.PeekData(reg_byte_offset, reg_byte_size);
- if (restore_src)
+ // In case our register definitions don't include the correct offsets,
+ // keep track of the size of each reg & compute offset based on that.
+ uint32_t running_byte_offset = 0;
+ for (uint32_t reg_idx=0; (reg_info = GetRegisterInfoAtIndex (reg_idx)) != NULL; ++reg_idx, running_byte_offset += reg_info->byte_size)
{
- if (GetRegisterIsValid(reg))
+ // Skip composite aka slice registers (e.g. eax is a slice of rax).
+ if (reg_info->value_regs)
+ continue;
+
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+ uint32_t register_offset;
+ if (use_byte_offset_into_buffer)
{
- const char *current_src = (const char *)m_reg_data.PeekData(reg_byte_offset, reg_byte_size);
- if (current_src)
- write_reg = memcmp (current_src, restore_src, reg_byte_size) != 0;
+ register_offset = reg_info->byte_offset;
+ }
+ else
+ {
+ register_offset = running_byte_offset;
}
- if (write_reg)
+ // Only write down the registers that need to be written
+ // if we are going to be doing registers individually.
+ bool write_reg = true;
+ const uint32_t reg_byte_size = reg_info->byte_size;
+
+ const char *restore_src = (const char *)restore_data.PeekData(register_offset, reg_byte_size);
+ if (restore_src)
{
StreamString packet;
packet.Printf ("P%x=", reg);
@@ -662,14 +782,88 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
response,
false) == GDBRemoteCommunication::PacketResult::Success)
{
- if (response.IsOKResponse())
- ++num_restored;
+ const char *current_src = (const char *)m_reg_data.PeekData(register_offset, reg_byte_size);
+ if (current_src)
+ write_reg = memcmp (current_src, restore_src, reg_byte_size) != 0;
+ }
+
+ if (write_reg)
+ {
+ StreamString packet;
+ packet.Printf ("P%x=", reg);
+ packet.PutBytesAsRawHex8 (restore_src,
+ reg_byte_size,
+ lldb::endian::InlHostByteOrder(),
+ lldb::endian::InlHostByteOrder());
+
+ if (thread_suffix_supported)
+ packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
+
+ SetRegisterIsValid(reg, false);
+ if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
+ packet.GetString().size(),
+ response,
+ false) == GDBRemoteCommunication::PacketResult::Success)
+ {
+ if (response.IsOKResponse())
+ ++num_restored;
+ }
}
}
}
+ return num_restored > 0;
+ }
+ }
+ }
+ else
+ {
+ // For the use_g_packet == false case, we're going to write each register
+ // individually. The data buffer is binary data in this case, instead of
+ // ascii characters.
+
+ bool arm64_debugserver = false;
+ if (m_thread.GetProcess().get())
+ {
+ const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture();
+ if (arch.IsValid()
+ && arch.GetMachine() == llvm::Triple::aarch64
+ && arch.GetTriple().getVendor() == llvm::Triple::Apple
+ && arch.GetTriple().getOS() == llvm::Triple::IOS)
+ {
+ arm64_debugserver = true;
+ }
+ }
+ uint32_t num_restored = 0;
+ const RegisterInfo *reg_info;
+ for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex (i)) != NULL; i++)
+ {
+ if (reg_info->value_regs) // skip registers that are slices of real registers
+ continue;
+ // Skip the fpsr and fpcr floating point status/control register writing to
+ // work around a bug in an older version of debugserver that would lead to
+ // register context corruption when writing fpsr/fpcr.
+ if (arm64_debugserver &&
+ (strcmp (reg_info->name, "fpsr") == 0 || strcmp (reg_info->name, "fpcr") == 0))
+ {
+ continue;
+ }
+ StreamString packet;
+ packet.Printf ("P%x=", reg_info->kinds[eRegisterKindLLDB]);
+ packet.PutBytesAsRawHex8 (data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
+ if (thread_suffix_supported)
+ packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
+
+ SetRegisterIsValid(reg_info, false);
+ if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
+ packet.GetString().size(),
+ response,
+ false) == GDBRemoteCommunication::PacketResult::Success)
+ {
+ if (response.IsOKResponse())
+ ++num_restored;
}
- return num_restored > 0;
}
+ return num_restored > 0;
}
}
}
@@ -693,7 +887,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
uint32_t
-GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num)
{
return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num);
}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 38f29bbca0de..b77381458914 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -98,7 +98,7 @@ public:
WriteAllRegisterValues (const lldb_private::RegisterCheckpoint &reg_checkpoint);
virtual uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
protected:
friend class ThreadGDBRemote;
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 1172222d62a4..f35d954caa7b 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -56,11 +56,14 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
+#include "lldb/Target/SystemRuntime.h"
#include "lldb/Utility/PseudoTerminal.h"
// Project includes
#include "lldb/Host/Host.h"
+#include "Plugins/Process/Utility/FreeBSDSignals.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
+#include "Plugins/Process/Utility/LinuxSignals.h"
#include "Plugins/Process/Utility/StopInfoMachException.h"
#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
#include "Utility/StringExtractorGDBRemote.h"
@@ -166,8 +169,6 @@ namespace {
} // anonymous namespace end
-static bool rand_initialized = false;
-
// TODO Randomly assigning a port is unsafe. We should get an unused
// ephemeral port from the kernel and make sure we reserve it before passing
// it to debugserver.
@@ -180,19 +181,22 @@ static bool rand_initialized = false;
#define HIGH_PORT (49151u)
#endif
+#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
+static bool rand_initialized = false;
+
static inline uint16_t
get_random_port ()
{
if (!rand_initialized)
{
time_t seed = time(NULL);
-
+
rand_initialized = true;
srand(seed);
}
return (rand() % (HIGH_PORT - LOW_PORT)) + LOW_PORT;
}
-
+#endif
lldb_private::ConstString
ProcessGDBRemote::GetPluginNameStatic()
@@ -243,6 +247,7 @@ ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)
case ObjectFile::eTypeObjectFile:
case ObjectFile::eTypeSharedLibrary:
case ObjectFile::eTypeStubLibrary:
+ case ObjectFile::eTypeJIT:
return false;
case ObjectFile::eTypeExecutable:
case ObjectFile::eTypeDynamicLinker:
@@ -275,7 +280,8 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
m_continue_C_tids (),
m_continue_s_tids (),
m_continue_S_tids (),
- m_max_memory_size (512),
+ m_max_memory_size (0),
+ m_remote_stub_max_memory_size (0),
m_addr_to_mmap_size (),
m_thread_create_bp_sp (),
m_waiting_for_attach (false),
@@ -624,6 +630,7 @@ ProcessGDBRemote::WillAttachToProcessWithName (const char *process_name, bool wa
Error
ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
{
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Error error (WillLaunchOrAttach ());
if (error.Fail())
@@ -674,7 +681,11 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
error.SetErrorStringWithFormat ("Process %" PRIu64 " was reported after connecting to '%s', but no stop reply packet was received", pid, remote_url);
}
- if (error.Success()
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalizing target architecture initial triple: %s (GetTarget().GetArchitecture().IsValid() %s, m_gdb_comm.GetHostArchitecture().IsValid(): %s)", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str (), GetTarget ().GetArchitecture ().IsValid () ? "true" : "false", m_gdb_comm.GetHostArchitecture ().IsValid () ? "true" : "false");
+
+
+ if (error.Success()
&& !GetTarget().GetArchitecture().IsValid()
&& m_gdb_comm.GetHostArchitecture().IsValid())
{
@@ -685,6 +696,42 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture());
}
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalized target architecture triple: %s", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str ());
+
+ // Set the Unix signals properly for the target.
+ // FIXME Add a gdb-remote packet to discover dynamically.
+ if (error.Success ())
+ {
+ const ArchSpec arch_spec = GetTarget ().GetArchitecture ();
+ if (arch_spec.IsValid ())
+ {
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": determining unix signals type based on architecture %s, triple %s", __FUNCTION__, GetID (), arch_spec.GetArchitectureName () ? arch_spec.GetArchitectureName () : "<null>", arch_spec.GetTriple ().getTriple ().c_str ());
+
+ switch (arch_spec.GetTriple ().getOS ())
+ {
+ case llvm::Triple::Linux:
+ SetUnixSignals (UnixSignalsSP (new process_linux::LinuxSignals ()));
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s using Linux unix signals type for pid %" PRIu64, __FUNCTION__, GetID ());
+ break;
+ case llvm::Triple::OpenBSD:
+ case llvm::Triple::FreeBSD:
+ case llvm::Triple::NetBSD:
+ SetUnixSignals (UnixSignalsSP (new FreeBSDSignals ()));
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s using *BSD unix signals type for pid %" PRIu64, __FUNCTION__, GetID ());
+ break;
+ default:
+ SetUnixSignals (UnixSignalsSP (new UnixSignals ()));
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s using generic unix signals type for pid %" PRIu64, __FUNCTION__, GetID ());
+ break;
+ }
+ }
+ }
+
return error;
}
@@ -710,23 +757,23 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
const char *stderr_path = NULL;
const char *working_dir = launch_info.GetWorkingDirectory();
- const ProcessLaunchInfo::FileAction *file_action;
+ const FileAction *file_action;
file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
if (file_action)
{
- if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
+ if (file_action->GetAction() == FileAction::eFileActionOpen)
stdin_path = file_action->GetPath();
}
file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
if (file_action)
{
- if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
+ if (file_action->GetAction() == FileAction::eFileActionOpen)
stdout_path = file_action->GetPath();
}
file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
if (file_action)
{
- if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
+ if (file_action->GetAction() == FileAction::eFileActionOpen)
stderr_path = file_action->GetPath();
}
@@ -795,9 +842,14 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
m_gdb_comm.SetSTDERR (stderr_path);
m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);
+ m_gdb_comm.SetDetachOnError (launch_flags & eLaunchFlagDetachOnError);
m_gdb_comm.SendLaunchArchPacket (m_target.GetArchitecture().GetArchitectureName());
+ const char * launch_event_data = launch_info.GetLaunchEventData();
+ if (launch_event_data != NULL && *launch_event_data != '\0')
+ m_gdb_comm.SendLaunchEventDataPacket (launch_event_data);
+
if (working_dir && working_dir[0])
{
m_gdb_comm.SetWorkingDir (working_dir);
@@ -958,7 +1010,7 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
}
void
-ProcessGDBRemote::DidLaunchOrAttach ()
+ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)
{
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
if (log)
@@ -969,16 +1021,17 @@ ProcessGDBRemote::DidLaunchOrAttach ()
// See if the GDB server supports the qHostInfo information
- ArchSpec gdb_remote_arch = m_gdb_comm.GetHostArchitecture();
// See if the GDB server supports the qProcessInfo packet, if so
// prefer that over the Host information as it will be more specific
// to our process.
if (m_gdb_comm.GetProcessArchitecture().IsValid())
- gdb_remote_arch = m_gdb_comm.GetProcessArchitecture();
+ process_arch = m_gdb_comm.GetProcessArchitecture();
+ else
+ process_arch = m_gdb_comm.GetHostArchitecture();
- if (gdb_remote_arch.IsValid())
+ if (process_arch.IsValid())
{
ArchSpec &target_arch = GetTarget().GetArchitecture();
@@ -991,15 +1044,15 @@ ProcessGDBRemote::DidLaunchOrAttach ()
// it has, so we really need to take the remote host architecture as our
// defacto architecture in this case.
- if (gdb_remote_arch.GetMachine() == llvm::Triple::arm &&
- gdb_remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)
+ if (process_arch.GetMachine() == llvm::Triple::arm &&
+ process_arch.GetTriple().getVendor() == llvm::Triple::Apple)
{
- target_arch = gdb_remote_arch;
+ GetTarget().SetArchitecture (process_arch);
}
else
{
// Fill in what is missing in the triple
- const llvm::Triple &remote_triple = gdb_remote_arch.GetTriple();
+ const llvm::Triple &remote_triple = process_arch.GetTriple();
llvm::Triple &target_triple = target_arch.GetTriple();
if (target_triple.getVendorName().size() == 0)
{
@@ -1019,7 +1072,7 @@ ProcessGDBRemote::DidLaunchOrAttach ()
{
// The target doesn't have a valid architecture yet, set it from
// the architecture we got from the remote GDB server
- target_arch = gdb_remote_arch;
+ GetTarget().SetArchitecture (process_arch);
}
}
}
@@ -1028,7 +1081,8 @@ ProcessGDBRemote::DidLaunchOrAttach ()
void
ProcessGDBRemote::DidLaunch ()
{
- DidLaunchOrAttach ();
+ ArchSpec process_arch;
+ DidLaunchOrAttach (process_arch);
}
Error
@@ -1063,6 +1117,8 @@ 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);
@@ -1100,6 +1156,8 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const Pro
{
StreamString packet;
+ m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
+
if (attach_info.GetWaitForLaunch())
{
if (!m_gdb_comm.GetVAttachOrWaitSupported())
@@ -1135,9 +1193,11 @@ ProcessGDBRemote::SetExitStatus (int exit_status, const char *cstr)
}
void
-ProcessGDBRemote::DidAttach ()
+ProcessGDBRemote::DidAttach (ArchSpec &process_arch)
{
- DidLaunchOrAttach ();
+ // If you can figure out what the architecture is, fill it in here.
+ process_arch.Clear();
+ DidLaunchOrAttach (process_arch);
}
@@ -1452,8 +1512,7 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new
if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
log->Printf(
"ProcessGDBRemote::%s Making new thread: %p for thread ID: 0x%" PRIx64 ".\n",
- __FUNCTION__,
- thread_sp.get(),
+ __FUNCTION__, static_cast<void*>(thread_sp.get()),
thread_sp->GetID());
}
else
@@ -1461,8 +1520,7 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new
if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
log->Printf(
"ProcessGDBRemote::%s Found old thread: %p for thread ID: 0x%" PRIx64 ".\n",
- __FUNCTION__,
- thread_sp.get(),
+ __FUNCTION__, static_cast<void*>(thread_sp.get()),
thread_sp->GetID());
}
new_thread_list.AddThread(thread_sp);
@@ -1557,9 +1615,9 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
log->Printf ("ProcessGDBRemote::%s Adding new thread: %p for thread ID: 0x%" PRIx64 ".\n",
__FUNCTION__,
- thread_sp.get(),
+ static_cast<void*>(thread_sp.get()),
thread_sp->GetID());
-
+
m_thread_list_real.AddThread(thread_sp);
}
gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
@@ -1582,7 +1640,6 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
if (tid != LLDB_INVALID_THREAD_ID)
m_thread_ids.push_back (tid);
value.erase(0, comma_pos + 1);
-
}
tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
if (tid != LLDB_INVALID_THREAD_ID)
@@ -1709,7 +1766,6 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
thread_sp->SetStopInfo (invalid_stop_info_sp);
}
}
-
}
else if (reason.compare("trap") == 0)
{
@@ -1734,7 +1790,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
handled = true;
}
}
-
+
if (!handled && signo && did_exec == false)
{
if (signo == SIGTRAP)
@@ -1744,7 +1800,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
handled = true;
addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset;
lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
-
+
if (bp_site_sp)
{
// If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
@@ -1776,7 +1832,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
if (!handled)
thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo));
}
-
+
if (!description.empty())
{
lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
@@ -1796,6 +1852,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
break;
case 'W':
+ case 'X':
// process exited
return eStateExited;
@@ -1864,10 +1921,6 @@ ProcessGDBRemote::DoDetach(bool keep_stopped)
if (log)
log->Printf ("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped);
- DisableAllBreakpointSites ();
-
- m_thread_list.DiscardThreadPlans();
-
error = m_gdb_comm.Detach (keep_stopped);
if (log)
{
@@ -1928,7 +1981,7 @@ ProcessGDBRemote::DoDestroy ()
if (m_destroy_tried_resuming)
{
if (log)
- log->PutCString ("ProcessGDBRemote::DoDestroy()Tried resuming to destroy once already, not doing it again.");
+ log->PutCString ("ProcessGDBRemote::DoDestroy() - Tried resuming to destroy once already, not doing it again.");
}
else
{
@@ -2064,7 +2117,7 @@ ProcessGDBRemote::DoDestroy ()
else
{
if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy - failed to send k packet");
+ log->Printf ("ProcessGDBRemote::DoDestroy - killed or interrupted while attaching");
exit_string.assign ("killed or interrupted while attaching.");
}
}
@@ -2124,6 +2177,7 @@ ProcessGDBRemote::GetImageInfoAddress()
size_t
ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
{
+ GetMaxMemorySize ();
if (size > m_max_memory_size)
{
// Keep memory read sizes down to a sane limit. This function will be
@@ -2133,7 +2187,16 @@ ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &erro
}
char packet[64];
- const int packet_len = ::snprintf (packet, sizeof(packet), "m%" PRIx64 ",%" PRIx64, (uint64_t)addr, (uint64_t)size);
+ int packet_len;
+ bool binary_memory_read = m_gdb_comm.GetxPacketSupported();
+ if (binary_memory_read)
+ {
+ packet_len = ::snprintf (packet, sizeof(packet), "x0x%" PRIx64 ",0x%" PRIx64, (uint64_t)addr, (uint64_t)size);
+ }
+ else
+ {
+ packet_len = ::snprintf (packet, sizeof(packet), "m%" PRIx64 ",%" PRIx64, (uint64_t)addr, (uint64_t)size);
+ }
assert (packet_len + 1 < (int)sizeof(packet));
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true) == GDBRemoteCommunication::PacketResult::Success)
@@ -2141,7 +2204,25 @@ ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &erro
if (response.IsNormalResponse())
{
error.Clear();
- return response.GetHexBytes(buf, size, '\xdd');
+ if (binary_memory_read)
+ {
+ // The lower level GDBRemoteCommunication packet receive layer has already de-quoted any
+ // 0x7d character escaping that was present in the packet
+
+ size_t data_received_size = response.GetBytesLeft();
+ if (data_received_size > size)
+ {
+ // Don't write past the end of BUF if the remote debug server gave us too
+ // much data for some reason.
+ data_received_size = size;
+ }
+ memcpy (buf, response.GetStringRef().data(), data_received_size);
+ return data_received_size;
+ }
+ else
+ {
+ return response.GetHexBytes(buf, size, '\xdd');
+ }
}
else if (response.IsErrorResponse())
error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr);
@@ -2160,6 +2241,7 @@ ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &erro
size_t
ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
{
+ GetMaxMemorySize ();
if (size > m_max_memory_size)
{
// Keep memory read sizes down to a sane limit. This function will be
@@ -2196,6 +2278,7 @@ ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Erro
lldb::addr_t
ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
{
+ lldb_private::Log *log (lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_EXPRESSIONS));
addr_t allocated_addr = LLDB_INVALID_ADDRESS;
LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory();
@@ -2221,7 +2304,11 @@ ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &er
eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0))
m_addr_to_mmap_size[allocated_addr] = size;
else
+ {
allocated_addr = LLDB_INVALID_ADDRESS;
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s no direct stub support for memory allocation, and InferiorCallMmap also failed - is stub missing register context save/restore capability?", __FUNCTION__);
+ }
break;
}
@@ -2393,7 +2480,7 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site)
return error;
}
- // We will reach here when the stub gives an unsported response to a hardware breakpoint
+ // We will reach here when the stub gives an unsupported response to a hardware breakpoint
if (log)
log->Printf("Hardware breakpoints are unsupported");
@@ -2440,8 +2527,16 @@ ProcessGDBRemote::DisableBreakpointSite (BreakpointSite *bp_site)
break;
case BreakpointSite::eExternal:
- if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
+ {
+ GDBStoppointType stoppoint_type;
+ if (bp_site->IsHardware())
+ stoppoint_type = eBreakpointHardware;
+ else
+ stoppoint_type = eBreakpointSoftware;
+
+ if (m_gdb_comm.SendGDBStoppointTypePacket(stoppoint_type, false, addr, bp_op_size))
error.SetErrorToGenericError();
+ }
break;
}
if (error.Success())
@@ -2602,9 +2697,9 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
debugserver_launch_info.SetMonitorProcessCallback (MonitorDebugserverProcess, this, false);
debugserver_launch_info.SetUserID(process_info.GetUserID());
-#if defined (__APPLE__) && defined (__arm__)
+#if defined (__APPLE__) && (defined (__arm__) || defined (__arm64__) || defined (__aarch64__))
// On iOS, still do a local connection using a random port
- const char *hostname = "localhost";
+ const char *hostname = "127.0.0.1";
uint16_t port = get_random_port ();
#else
// Set hostname being NULL to do the reverse connect where debugserver
@@ -2918,13 +3013,33 @@ ProcessGDBRemote::AsyncThread (void *arg)
break;
case eStateExited:
+ {
process->SetLastStopPacket (response);
process->ClearThreadIDList();
response.SetFilePos(1);
- process->SetExitStatus(response.GetHexU8(), NULL);
+
+ int exit_status = response.GetHexU8();
+ const char *desc_cstr = NULL;
+ StringExtractor extractor;
+ std::string desc_string;
+ if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';')
+ {
+ std::string desc_token;
+ while (response.GetNameColonValue (desc_token, desc_string))
+ {
+ if (desc_token == "description")
+ {
+ extractor.GetStringRef().swap(desc_string);
+ extractor.SetFilePos(0);
+ extractor.GetHexByteString (desc_string);
+ desc_cstr = desc_string.c_str();
+ }
+ }
+ }
+ process->SetExitStatus(exit_status, desc_cstr);
done = true;
break;
-
+ }
case eStateInvalid:
process->SetExitStatus(-1, "lost connection");
break;
@@ -3060,6 +3175,146 @@ ProcessGDBRemote::GetDynamicLoader ()
return m_dyld_ap.get();
}
+Error
+ProcessGDBRemote::SendEventData(const char *data)
+{
+ int return_value;
+ bool was_supported;
+
+ Error error;
+
+ return_value = m_gdb_comm.SendLaunchEventDataPacket (data, &was_supported);
+ if (return_value != 0)
+ {
+ if (!was_supported)
+ error.SetErrorString("Sending events is not supported for this process.");
+ else
+ error.SetErrorStringWithFormat("Error sending event data: %d.", return_value);
+ }
+ return error;
+}
+
+const DataBufferSP
+ProcessGDBRemote::GetAuxvData()
+{
+ DataBufferSP buf;
+ if (m_gdb_comm.GetQXferAuxvReadSupported())
+ {
+ std::string response_string;
+ if (m_gdb_comm.SendPacketsAndConcatenateResponses("qXfer:auxv:read::", response_string) == GDBRemoteCommunication::PacketResult::Success)
+ buf.reset(new DataBufferHeap(response_string.c_str(), response_string.length()));
+ }
+ return buf;
+}
+
+StructuredData::ObjectSP
+ProcessGDBRemote::GetExtendedInfoForThread (lldb::tid_t tid)
+{
+ StructuredData::ObjectSP object_sp;
+
+ if (m_gdb_comm.GetThreadExtendedInfoSupported())
+ {
+ StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+ SystemRuntime *runtime = GetSystemRuntime();
+ if (runtime)
+ {
+ runtime->AddThreadExtendedInfoPacketHints (args_dict);
+ }
+ args_dict->GetAsDictionary()->AddIntegerItem ("thread", tid);
+
+ StreamString packet;
+ packet << "jThreadExtendedInfo:";
+ args_dict->Dump (packet);
+
+ // FIXME the final character of a JSON dictionary, '}', is the escape
+ // character in gdb-remote binary mode. lldb currently doesn't escape
+ // these characters in its packet output -- so we add the quoted version
+ // of the } character here manually in case we talk to a debugserver which
+ // un-escapes the characters at packet read time.
+ packet << (char) (0x7d ^ 0x20);
+
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success)
+ {
+ StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType();
+ if (response_type == StringExtractorGDBRemote::eResponse)
+ {
+ if (!response.Empty())
+ {
+ // The packet has already had the 0x7d xor quoting stripped out at the
+ // GDBRemoteCommunication packet receive level.
+ object_sp = StructuredData::ParseJSON (response.GetStringRef());
+ }
+ }
+ }
+ }
+ return object_sp;
+}
+
+// Establish the largest memory read/write payloads we should use.
+// If the remote stub has a max packet size, stay under that size.
+//
+// If the remote stub's max packet size is crazy large, use a
+// reasonable largeish default.
+//
+// If the remote stub doesn't advertise a max packet size, use a
+// conservative default.
+
+void
+ProcessGDBRemote::GetMaxMemorySize()
+{
+ const uint64_t reasonable_largeish_default = 128 * 1024;
+ const uint64_t conservative_default = 512;
+
+ if (m_max_memory_size == 0)
+ {
+ uint64_t stub_max_size = m_gdb_comm.GetRemoteMaxPacketSize();
+ if (stub_max_size != UINT64_MAX && stub_max_size != 0)
+ {
+ // Save the stub's claimed maximum packet size
+ m_remote_stub_max_memory_size = stub_max_size;
+
+ // Even if the stub says it can support ginormous packets,
+ // don't exceed our reasonable largeish default packet size.
+ if (stub_max_size > reasonable_largeish_default)
+ {
+ stub_max_size = reasonable_largeish_default;
+ }
+
+ m_max_memory_size = stub_max_size;
+ }
+ else
+ {
+ m_max_memory_size = conservative_default;
+ }
+ }
+}
+
+void
+ProcessGDBRemote::SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max)
+{
+ if (user_specified_max != 0)
+ {
+ GetMaxMemorySize ();
+
+ if (m_remote_stub_max_memory_size != 0)
+ {
+ if (m_remote_stub_max_memory_size < user_specified_max)
+ {
+ m_max_memory_size = m_remote_stub_max_memory_size; // user specified a packet size too big, go as big
+ // as the remote stub says we can go.
+ }
+ else
+ {
+ m_max_memory_size = user_specified_max; // user's packet size is good
+ }
+ }
+ else
+ {
+ m_max_memory_size = user_specified_max; // user's packet size is probably fine
+ }
+ }
+}
class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed
{
@@ -3101,6 +3356,53 @@ public:
}
};
+class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed
+{
+private:
+
+public:
+ CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "process plugin packet xfer-size",
+ "Maximum size that lldb will try to read/write one one chunk.",
+ NULL)
+ {
+ }
+
+ ~CommandObjectProcessGDBRemotePacketXferSize ()
+ {
+ }
+
+ bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0)
+ {
+ result.AppendErrorWithFormat ("'%s' takes an argument to specify the max amount to be transferred when reading/writing", m_cmd_name.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
+ if (process)
+ {
+ const char *packet_size = command.GetArgumentAtIndex(0);
+ errno = 0;
+ uint64_t user_specified_max = strtoul (packet_size, NULL, 10);
+ if (errno == 0 && user_specified_max != 0)
+ {
+ process->SetUserSpecifiedMaxMemoryTransferSize (user_specified_max);
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ }
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+};
+
+
class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed
{
private:
@@ -3226,6 +3528,7 @@ public:
LoadSubCommand ("history", CommandObjectSP (new CommandObjectProcessGDBRemotePacketHistory (interpreter)));
LoadSubCommand ("send", CommandObjectSP (new CommandObjectProcessGDBRemotePacketSend (interpreter)));
LoadSubCommand ("monitor", CommandObjectSP (new CommandObjectProcessGDBRemotePacketMonitor (interpreter)));
+ LoadSubCommand ("xfer-size", CommandObjectSP (new CommandObjectProcessGDBRemotePacketXferSize (interpreter)));
}
~CommandObjectProcessGDBRemotePacket ()
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 9331775bb896..942b31c84dde 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -23,7 +23,9 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/StringList.h"
+#include "lldb/Core/StructuredData.h"
#include "lldb/Core/ThreadSafeValue.h"
+#include "lldb/lldb-private-forward.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
@@ -113,7 +115,7 @@ public:
const lldb_private::ProcessAttachInfo &attach_info);
virtual void
- DidAttach ();
+ DidAttach (lldb_private::ArchSpec &process_arch);
//------------------------------------------------------------------
// PluginInterface protocol
@@ -221,12 +223,17 @@ public:
return m_gdb_comm;
}
+ virtual lldb_private::Error
+ SendEventData(const char *data);
+
//----------------------------------------------------------------------
// Override SetExitStatus so we can disconnect from the remote GDB server
//----------------------------------------------------------------------
virtual bool
SetExitStatus (int exit_status, const char *cstr);
+ void
+ SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max);
protected:
friend class ThreadGDBRemote;
@@ -299,6 +306,15 @@ protected:
bool
ParseRegisters(lldb_private::ScriptInterpreterObject *registers_array);
+ const lldb::DataBufferSP
+ GetAuxvData() override;
+
+ lldb_private::StructuredData::ObjectSP
+ GetExtendedInfoForThread (lldb::tid_t tid);
+
+ void
+ GetMaxMemorySize();
+
//------------------------------------------------------------------
/// Broadcaster event bits definitions.
//------------------------------------------------------------------
@@ -334,14 +350,15 @@ protected:
tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
tid_collection m_continue_s_tids; // 's' for step
tid_sig_collection m_continue_S_tids; // 'S' for step with signal
- size_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
+ uint64_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
+ uint64_t m_remote_stub_max_memory_size; // The maximum memory size the remote gdb stub can handle
MMapMap m_addr_to_mmap_size;
lldb::BreakpointSP m_thread_create_bp_sp;
bool m_waiting_for_attach;
bool m_destroy_tried_resuming;
lldb::CommandObjectSP m_command_sp;
int64_t m_breakpoint_pc_offset;
-
+
bool
StartAsyncThread ();
@@ -368,7 +385,7 @@ protected:
UpdateThreadIDList ();
void
- DidLaunchOrAttach ();
+ DidLaunchOrAttach (lldb_private::ArchSpec& process_arch);
lldb_private::Error
ConnectToDebugserver (const char *host_port);
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index fb524deda813..5c70cb5427cb 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -107,6 +107,58 @@ ThreadGDBRemote::GetQueueID ()
return LLDB_INVALID_QUEUE_ID;
}
+QueueSP
+ThreadGDBRemote::GetQueue ()
+{
+ queue_id_t queue_id = GetQueueID();
+ QueueSP queue;
+ if (queue_id != LLDB_INVALID_QUEUE_ID)
+ {
+ ProcessSP process_sp (GetProcess());
+ if (process_sp)
+ {
+ queue = process_sp->GetQueueList().FindQueueByID (queue_id);
+ }
+ }
+ return queue;
+}
+
+addr_t
+ThreadGDBRemote::GetQueueLibdispatchQueueAddress ()
+{
+ addr_t dispatch_queue_t_addr = LLDB_INVALID_ADDRESS;
+ if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+ {
+ ProcessSP process_sp (GetProcess());
+ if (process_sp)
+ {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime ();
+ if (runtime)
+ {
+ dispatch_queue_t_addr = runtime->GetLibdispatchQueueAddressFromThreadQAddress (m_thread_dispatch_qaddr);
+ }
+ }
+ }
+ return dispatch_queue_t_addr;
+}
+
+StructuredData::ObjectSP
+ThreadGDBRemote::FetchThreadExtendedInfo ()
+{
+ StructuredData::ObjectSP object_sp;
+ const lldb::user_id_t tid = GetProtocolID();
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (GDBR_LOG_THREAD));
+ if (log)
+ log->Printf ("Fetching extended information for thread %4.4" PRIx64, tid);
+ ProcessSP process_sp (GetProcess());
+ if (process_sp)
+ {
+ ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
+ object_sp = gdb_process->GetExtendedInfoForThread (tid);
+ }
+ return object_sp;
+}
+
void
ThreadGDBRemote::WillResume (StateType resume_state)
{
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index dd4cc036ef8b..a204a917ecb3 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -12,6 +12,7 @@
#include <string>
+#include "lldb/Core/StructuredData.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
@@ -41,6 +42,12 @@ public:
virtual lldb::queue_id_t
GetQueueID ();
+ virtual lldb::QueueSP
+ GetQueue ();
+
+ lldb::addr_t
+ GetQueueLibdispatchQueueAddress ();
+
virtual lldb::RegisterContextSP
GetRegisterContext ();
@@ -80,6 +87,9 @@ public:
m_thread_dispatch_qaddr = thread_dispatch_qaddr;
}
+ lldb_private::StructuredData::ObjectSP
+ FetchThreadExtendedInfo ();
+
protected:
friend class ProcessGDBRemote;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
index ff2e3762556a..bc2e7a62b76e 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -92,84 +92,6 @@ DWARFAbbreviationDeclaration::IsValid()
}
-void
-DWARFAbbreviationDeclaration::CopyExcludingAddressAttributes(const DWARFAbbreviationDeclaration& abbr_decl, const uint32_t idx)
-{
- m_code = abbr_decl.Code(); // Invalidate the code since that can't be copied safely.
- m_tag = abbr_decl.Tag();
- m_has_children = abbr_decl.HasChildren();
-
- const DWARFAttribute::collection& attributes = abbr_decl.Attributes();
- const uint32_t num_abbr_decl_attributes = attributes.size();
-
- dw_attr_t attr;
- dw_form_t form;
- uint32_t i;
-
- for (i = 0; i < num_abbr_decl_attributes; ++i)
- {
- attributes[i].get(attr, form);
- switch (attr)
- {
- case DW_AT_location:
- case DW_AT_frame_base:
- // Only add these if they are location expressions (have a single
- // value) and not location lists (have a lists of location
- // expressions which are only valid over specific address ranges)
- if (DWARFFormValue::IsBlockForm(form))
- m_attributes.push_back(DWARFAttribute(attr, form));
- break;
-
- case DW_AT_low_pc:
- case DW_AT_high_pc:
- case DW_AT_ranges:
- case DW_AT_entry_pc:
- // Don't add these attributes
- if (i >= idx)
- break;
- // Fall through and add attribute
- default:
- // Add anything that isn't address related
- m_attributes.push_back(DWARFAttribute(attr, form));
- break;
- }
- }
-}
-
-void
-DWARFAbbreviationDeclaration::CopyChangingStringToStrp(
- const DWARFAbbreviationDeclaration& abbr_decl,
- const DWARFDataExtractor& debug_info_data,
- dw_offset_t debug_info_offset,
- const DWARFCompileUnit* cu,
- const uint32_t strp_min_len
-)
-{
- m_code = InvalidCode;
- m_tag = abbr_decl.Tag();
- m_has_children = abbr_decl.HasChildren();
-
- const DWARFAttribute::collection& attributes = abbr_decl.Attributes();
- const uint32_t num_abbr_decl_attributes = attributes.size();
-
- dw_attr_t attr;
- dw_form_t form;
- uint32_t i;
- lldb::offset_t offset = debug_info_offset;
-
- for (i = 0; i < num_abbr_decl_attributes; ++i)
- {
- attributes[i].get(attr, form);
- dw_offset_t attr_offset = offset;
- DWARFFormValue::SkipValue(form, debug_info_data, &offset, cu);
-
- if (form == DW_FORM_string && ((offset - attr_offset) >= strp_min_len))
- m_attributes.push_back(DWARFAttribute(attr, DW_FORM_strp));
- else
- m_attributes.push_back(DWARFAttribute(attr, form));
- }
-}
-
uint32_t
DWARFAbbreviationDeclaration::FindAttributeIndex(dw_attr_t attr) const
@@ -193,19 +115,3 @@ DWARFAbbreviationDeclaration::operator == (const DWARFAbbreviationDeclaration& r
&& Attributes() == rhs.Attributes();
}
-#if 0
-DWARFAbbreviationDeclaration::Append(BinaryStreamBuf& out_buff) const
-{
- out_buff.Append32_as_ULEB128(Code());
- out_buff.Append32_as_ULEB128(Tag());
- out_buff.Append8(HasChildren());
- const uint32_t kNumAttributes = m_attributes.size();
- for (uint32_t i = 0; i < kNumAttributes; ++i)
- {
- out_buff.Append32_as_ULEB128(m_attributes[i].attr());
- out_buff.Append32_as_ULEB128(m_attributes[i].form());
- }
- out_buff.Append8(0); // Output a zero for attr (faster than using Append32_as_ULEB128)
- out_buff.Append8(0); // Output a zero for attr (faster than using Append32_as_ULEB128)
-}
-#endif // 0
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
index 48b9ebe37ee7..0ef153a704cd 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
@@ -55,21 +55,12 @@ public:
{
return m_attributes[idx].get_form();
}
- void CopyExcludingAddressAttributes(const DWARFAbbreviationDeclaration& abbr_decl, const uint32_t idx);
- void CopyChangingStringToStrp(
- const DWARFAbbreviationDeclaration& abbr_decl,
- const lldb_private::DWARFDataExtractor& debug_info_data,
- dw_offset_t debug_info_offset,
- const DWARFCompileUnit* cu,
- const uint32_t strp_min_len);
uint32_t FindAttributeIndex(dw_attr_t attr) const;
bool Extract(const lldb_private::DWARFDataExtractor& data, lldb::offset_t *offset_ptr);
bool Extract(const lldb_private::DWARFDataExtractor& data, lldb::offset_t *offset_ptr, dw_uleb128_t code);
-// void Append(BinaryStreamBuf& out_buff) const;
bool IsValid();
void Dump(lldb_private::Stream *s) const;
bool operator == (const DWARFAbbreviationDeclaration& rhs) const;
-// DWARFAttribute::collection& Attributes() { return m_attributes; }
const DWARFAttribute::collection& Attributes() const { return m_attributes; }
protected:
dw_uleb128_t m_code;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index cf664db28acd..b2e64ad9f8c8 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -265,12 +265,16 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
DWARFDebugInfoEntry::collection exact_size_die_array (m_die_array.begin(), m_die_array.end());
exact_size_die_array.swap (m_die_array);
}
- Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_DEBUG_INFO | DWARF_LOG_VERBOSE));
- if (log)
+ Log *verbose_log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_DEBUG_INFO | DWARF_LOG_VERBOSE));
+ if (verbose_log)
{
StreamString strm;
- DWARFDebugInfoEntry::DumpDIECollection (strm, m_die_array);
- log->PutCString (strm.GetString().c_str());
+ Dump(&strm);
+ if (m_die_array.empty())
+ strm.Printf("error: no DIE for compile unit");
+ else
+ m_die_array[0].Dump(m_dwarf2Data, this, strm, UINT32_MAX);
+ verbose_log->PutCString (strm.GetString().c_str());
}
return m_die_array.size();
@@ -357,18 +361,43 @@ DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size)
void
DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
- DWARFDebugAranges* debug_aranges,
- bool clear_dies_if_already_not_parsed)
+ DWARFDebugAranges* debug_aranges)
{
// This function is usually called if there in no .debug_aranges section
// in order to produce a compile unit level set of address ranges that
- // is accurate. If the DIEs weren't parsed, then we don't want all dies for
- // all compile units to stay loaded when they weren't needed. So we can end
- // up parsing the DWARF and then throwing them all away to keep memory usage
- // down.
+ // is accurate.
+
+ // First get the compile unit DIE only and check if it has a DW_AT_ranges
+ const DWARFDebugInfoEntry* die = GetCompileUnitDIEOnly();
+
+ const dw_offset_t cu_offset = GetOffset();
+ if (die)
+ {
+ DWARFDebugRanges::RangeList ranges;
+ const size_t num_ranges = die->GetAttributeAddressRanges(dwarf2Data, this, ranges, false);
+ if (num_ranges > 0)
+ {
+ // This compile unit has DW_AT_ranges, assume this is correct if it
+ // is present since clang no longer makes .debug_aranges by default
+ // and it emits DW_AT_ranges for DW_TAG_compile_units. GCC also does
+ // this with recent GCC builds.
+ for (size_t i=0; i<num_ranges; ++i)
+ {
+ const DWARFDebugRanges::RangeList::Entry &range = ranges.GetEntryRef(i);
+ debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd());
+ }
+
+ return; // We got all of our ranges from the DW_AT_ranges attribute
+ }
+ }
+ // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF
+
+ // If the DIEs weren't parsed, then we don't want all dies for all compile units
+ // to stay loaded when they weren't needed. So we can end up parsing the DWARF
+ // and then throwing them all away to keep memory usage down.
const bool clear_dies = ExtractDIEsIfNeeded (false) > 1;
- const DWARFDebugInfoEntry* die = DIE();
+ die = DIE();
if (die)
die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges);
@@ -393,7 +422,7 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
for (uint32_t idx=0; idx<num_ranges; ++idx)
{
const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx);
- debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
+ debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd());
printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
}
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
index 35597f389423..ed1894b8a9f6 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -54,8 +54,7 @@ public:
dw_addr_t GetBaseAddress() const { return m_base_addr; }
void ClearDIEs(bool keep_compile_unit_die);
void BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
- DWARFDebugAranges* debug_aranges,
- bool clear_dies_if_already_not_parsed);
+ DWARFDebugAranges* debug_aranges);
void
SetBaseAddress(dw_addr_t base_addr)
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
index d083f8a615c4..b0b71368b800 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
@@ -188,38 +188,74 @@ DWARFDebugArangeSet::Extract(const DWARFDataExtractor &data, lldb::offset_t *off
m_header.cu_offset = data.GetDWARFOffset(offset_ptr);
m_header.addr_size = data.GetU8(offset_ptr);
m_header.seg_size = data.GetU8(offset_ptr);
-
-
- // The first tuple following the header in each set begins at an offset
- // that is a multiple of the size of a single tuple (that is, twice the
- // size of an address). The header is padded, if necessary, to the
- // appropriate boundary.
- const uint32_t header_size = *offset_ptr - m_offset;
- const uint32_t tuple_size = m_header.addr_size << 1;
- uint32_t first_tuple_offset = 0;
- while (first_tuple_offset < header_size)
- first_tuple_offset += tuple_size;
-
- *offset_ptr = m_offset + first_tuple_offset;
-
- Descriptor arangeDescriptor;
-
- assert(sizeof(arangeDescriptor.address) == sizeof(arangeDescriptor.length));
- assert(sizeof(arangeDescriptor.address) >= m_header.addr_size);
-
- while (data.ValidOffset(*offset_ptr))
+
+ // Try to avoid reading invalid arange sets by making sure:
+ // 1 - the version looks good
+ // 2 - the address byte size looks plausible
+ // 3 - the length seems to make sense
+ // size looks plausible
+ if ((m_header.version >= 2 && m_header.version <= 5) &&
+ (m_header.addr_size == 4 || m_header.addr_size == 8) &&
+ (m_header.length > 0))
{
- arangeDescriptor.address = data.GetMaxU64(offset_ptr, m_header.addr_size);
- arangeDescriptor.length = data.GetMaxU64(offset_ptr, m_header.addr_size);
-
- // Each set of tuples is terminated by a 0 for the address and 0
- // for the length.
- if (arangeDescriptor.address || arangeDescriptor.length)
- m_arange_descriptors.push_back(arangeDescriptor);
+ if (data.ValidOffset(m_offset + sizeof(m_header.length) + m_header.length - 1))
+ {
+ // The first tuple following the header in each set begins at an offset
+ // that is a multiple of the size of a single tuple (that is, twice the
+ // size of an address). The header is padded, if necessary, to the
+ // appropriate boundary.
+ const uint32_t header_size = *offset_ptr - m_offset;
+ const uint32_t tuple_size = m_header.addr_size << 1;
+ uint32_t first_tuple_offset = 0;
+ while (first_tuple_offset < header_size)
+ first_tuple_offset += tuple_size;
+
+ *offset_ptr = m_offset + first_tuple_offset;
+
+ Descriptor arangeDescriptor;
+
+ static_assert(sizeof(arangeDescriptor.address) == sizeof(arangeDescriptor.length),
+ "DWARFDebugArangeSet::Descriptor.address and DWARFDebugArangeSet::Descriptor.length must have same size");
+
+ while (data.ValidOffset(*offset_ptr))
+ {
+ arangeDescriptor.address = data.GetMaxU64(offset_ptr, m_header.addr_size);
+ arangeDescriptor.length = data.GetMaxU64(offset_ptr, m_header.addr_size);
+
+ // Each set of tuples is terminated by a 0 for the address and 0
+ // for the length.
+ if (arangeDescriptor.address || arangeDescriptor.length)
+ m_arange_descriptors.push_back(arangeDescriptor);
+ else
+ break; // We are done if we get a zero address and length
+ }
+ }
+#if defined (LLDB_CONFIGURATION_DEBUG)
else
- break; // We are done if we get a zero address and length
+ {
+ printf ("warning: .debug_arange set length is too large arange data at 0x%8.8x: length=0x%8.8x, version=0x%4.4x, cu_offset=0x%8.8x, addr_size=%u, seg_size=%u\n",
+ m_offset,
+ m_header.length,
+ m_header.version,
+ m_header.cu_offset,
+ m_header.addr_size,
+ m_header.seg_size);
+ }
+#endif
}
-
+#if defined (LLDB_CONFIGURATION_DEBUG)
+ else
+ {
+ printf ("warning: .debug_arange set has bad header at 0x%8.8x: length=0x%8.8x, version=0x%4.4x, cu_offset=0x%8.8x, addr_size=%u, seg_size=%u\n",
+ m_offset,
+ m_header.length,
+ m_header.version,
+ m_header.cu_offset,
+ m_header.addr_size,
+ m_header.seg_size);
+ }
+#endif
+
return !m_arange_descriptors.empty();
}
return false;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
index 4f77bff86bdc..60e5c6ed62fe 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
@@ -93,14 +93,13 @@ DWARFDebugAranges::Generate(SymbolFileDWARF* dwarf2Data)
DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
if (debug_info)
{
- const bool clear_dies_if_already_not_parsed = true;
uint32_t cu_idx = 0;
const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
{
DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
if (cu)
- cu->BuildAddressRangeTable(dwarf2Data, this, clear_dies_if_already_not_parsed);
+ cu->BuildAddressRangeTable(dwarf2Data, this);
}
}
return !IsEmpty();
@@ -136,7 +135,7 @@ void
DWARFDebugAranges::Sort (bool minimize)
{
Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p",
- __PRETTY_FUNCTION__, this);
+ __PRETTY_FUNCTION__, static_cast<void*>(this));
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
size_t orig_arange_size = 0;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index d4db12c17a40..a8c553e2d2ca 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -79,7 +79,6 @@ DWARFDebugInfo::GetCompileUnitAranges ()
// Manually build arange data for everything that wasn't in the .debug_aranges table.
bool printed = false;
const size_t num_compile_units = GetNumCompileUnits();
- const bool clear_dies_if_already_not_parsed = true;
for (size_t idx = 0; idx < num_compile_units; ++idx)
{
DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx);
@@ -94,7 +93,7 @@ DWARFDebugInfo::GetCompileUnitAranges ()
m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
printed = true;
}
- cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get(), clear_dies_if_already_not_parsed);
+ cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get());
}
}
@@ -214,13 +213,6 @@ DWARFDebugInfo::ContainsCompileUnit (const DWARFCompileUnit *cu) const
return false;
}
-
-static bool CompileUnitOffsetLessThan (const DWARFCompileUnitSP& a, const DWARFCompileUnitSP& b)
-{
- return a->GetOffset() < b->GetOffset();
-}
-
-
static int
CompareDWARFCompileUnitSPOffset (const void *key, const void *arrmem)
{
@@ -280,15 +272,6 @@ DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset)
}
//----------------------------------------------------------------------
-// Compare function DWARFDebugAranges::Range structures
-//----------------------------------------------------------------------
-static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2)
-{
- return die1.GetOffset() < die2.GetOffset();
-}
-
-
-//----------------------------------------------------------------------
// GetDIE()
//
// Get the DIE (Debug Information Entry) with the specified offset.
@@ -341,40 +324,6 @@ DWARFDebugInfo::GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUn
}
//----------------------------------------------------------------------
-// DWARFDebugInfo_ParseCallback
-//
-// A callback function for the static DWARFDebugInfo::Parse() function
-// that gets parses all compile units and DIE's into an internate
-// representation for further modification.
-//----------------------------------------------------------------------
-
-static dw_offset_t
-DWARFDebugInfo_ParseCallback
-(
- SymbolFileDWARF* dwarf2Data,
- DWARFCompileUnitSP& cu_sp,
- DWARFDebugInfoEntry* die,
- const dw_offset_t next_offset,
- const uint32_t curr_depth,
- void* userData
-)
-{
- DWARFDebugInfo* debug_info = (DWARFDebugInfo*)userData;
- DWARFCompileUnit* cu = cu_sp.get();
- if (die)
- {
- cu->AddDIE(*die);
- }
- else if (cu)
- {
- debug_info->AddCompileUnit(cu_sp);
- }
-
- // Just return the current offset to parse the next CU or DIE entry
- return next_offset;
-}
-
-//----------------------------------------------------------------------
// AddCompileUnit
//----------------------------------------------------------------------
void
@@ -563,7 +512,7 @@ static dw_offset_t DumpCallback
// We have already found our DIE and are printing it's children. Obey
// our recurse depth and return an invalid offset if we get done
- // dumping all the the children
+ // dumping all of the children
if (dumpInfo->recurse_depth == UINT32_MAX || curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth)
die->Dump(dwarf2Data, cu, *s, 0);
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index 37741eb1da9c..856a7fa7a2ff 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -1485,6 +1485,40 @@ DWARFDebugInfoEntry::GetAttributeAddressRange
hi_pc = fail_value;
return false;
}
+
+size_t
+DWARFDebugInfoEntry::GetAttributeAddressRanges(SymbolFileDWARF* dwarf2Data,
+ const DWARFCompileUnit* cu,
+ DWARFDebugRanges::RangeList &ranges,
+ bool check_hi_lo_pc) const
+{
+ ranges.Clear();
+
+ dw_offset_t ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
+ if (ranges_offset != DW_INVALID_OFFSET)
+ {
+ dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
+ if (debug_ranges_offset != DW_INVALID_OFFSET)
+ {
+ DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
+
+ debug_ranges->FindRanges(debug_ranges_offset, ranges);
+ ranges.Slide (cu->GetBaseAddress());
+ }
+ }
+ else if (check_hi_lo_pc)
+ {
+ dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
+ dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
+ if (GetAttributeAddressRange (dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS))
+ {
+ if (lo_pc < hi_pc)
+ ranges.Append(DWARFDebugRanges::RangeList::Entry(lo_pc, hi_pc - lo_pc));
+ }
+ }
+ return ranges.GetSize();
+}
+
//----------------------------------------------------------------------
// GetAttributeValueAsLocation
//
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index f74057555286..3949ad339dd8 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -86,7 +86,7 @@ public:
dw_form_t form;
};
- typedef llvm::SmallVector<Info, 32> collection;
+ typedef llvm::SmallVector<Info, 8> collection;
collection m_infos;
};
@@ -209,7 +209,13 @@ public:
dw_addr_t& lo_pc,
dw_addr_t& hi_pc,
uint64_t fail_value) const;
-
+
+ size_t GetAttributeAddressRanges (
+ SymbolFileDWARF* dwarf2Data,
+ const DWARFCompileUnit* cu,
+ DWARFDebugRanges::RangeList &ranges,
+ bool check_hi_lo_pc) const;
+
dw_offset_t GetAttributeValueAsLocation(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
index 0a2f1f749409..6a2649463b54 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
@@ -256,7 +256,13 @@ DWARFDebugLine::DumpStatementOpcodes(Log *log, const DWARFDataExtractor& debug_l
prologue.file_names.push_back(fileEntry);
}
break;
-
+
+ case DW_LNE_set_discriminator:
+ {
+ uint64_t discriminator = debug_line_data.GetULEB128(&offset);
+ log->Printf( "0x%8.8x: DW_LNE_set_discriminator (0x%" PRIx64 ")", op_offset, discriminator);
+ }
+ break;
default:
log->Printf( "0x%8.8x: DW_LNE_??? (%2.2x) - Skipping unknown upcode", op_offset, opcode);
// Length doesn't include the zero opcode byte or the length itself, but
@@ -412,7 +418,7 @@ 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)
+ if (prologue->version < 2 || prologue->version > 3)
return false;
prologue->prologue_length = debug_line_data.GetDWARFOffset(offset_ptr);
@@ -480,7 +486,7 @@ 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)
+ if (version < 2 || version > 3)
return false;
const dw_offset_t end_prologue_offset = debug_line_data.GetDWARFOffset(&offset) + offset;
@@ -666,7 +672,7 @@ DWARFDebugLine::ParseStatementTable
// The files are numbered, starting at 1, in the order in which they
// appear; the names in the prologue come before names defined by
// the DW_LNE_define_file instruction. These numbers are used in the
- // the file register of the state machine.
+ // file register of the state machine.
{
FileNameEntry fileEntry;
fileEntry.name = debug_line_data.GetCStr(offset_ptr);
@@ -789,7 +795,7 @@ DWARFDebugLine::ParseStatementTable
// as a multiple of LEB128 operands for each opcode.
{
uint8_t i;
- assert (opcode - 1 < prologue->standard_opcode_lengths.size());
+ assert (static_cast<size_t>(opcode - 1) < prologue->standard_opcode_lengths.size());
const uint8_t opcode_length = prologue->standard_opcode_lengths[opcode - 1];
for (i=0; i<opcode_length; ++i)
debug_line_data.Skip_LEB128(offset_ptr);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
index 06ac825e0d4d..488e9820b6fa 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
@@ -66,11 +66,12 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
{
Timer scoped_timer (__PRETTY_FUNCTION__,
"DWARFDebugPubnames::GeneratePubnames (data = %p)",
- dwarf2Data);
+ static_cast<void*>(dwarf2Data));
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
if (log)
- log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)", dwarf2Data);
+ log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)",
+ static_cast<void*>(dwarf2Data));
m_sets.clear();
DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
index daa3b0aa6666..0953554ffd7d 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
@@ -143,7 +143,7 @@ DWARFDebugRanges::Dump(Stream &s, const DWARFDataExtractor& debug_ranges_data, l
{
dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
- // Extend 4 byte addresses that consits of 32 bits of 1's to be 64 bits
+ // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits
// of ones
if (begin == 0xFFFFFFFFull && addr_size == 4)
begin = LLDB_INVALID_ADDRESS;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
index abf69190c93c..5512072529fc 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
@@ -78,7 +78,7 @@ DWARFDeclContext::operator==(const DWARFDeclContext& rhs) const
collection::const_iterator rhs_begin = rhs.m_entries.begin();
// The two entry arrays have the same size
- // First compare the tags before we do expensize name compares
+ // First compare the tags before we do expensive name compares
for (pos = begin, rhs_pos = rhs_begin; pos != end; ++pos, ++rhs_pos)
{
if (pos->tag != rhs_pos->tag)
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index abd273770ddc..ab8e68ab5516 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -133,7 +133,7 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off
case DW_FORM_data8: m_value.value.uval = data.GetU64(offset_ptr); break;
case DW_FORM_string: m_value.value.cstr = data.GetCStr(offset_ptr);
// Set the string value to also be the data for inlined cstr form values only
- // so we can tell the differnence between DW_FORM_string and DW_FORM_strp form
+ // so we can tell the difference between DW_FORM_string and DW_FORM_strp form
// values;
m_value.data = (uint8_t*)m_value.value.cstr; break;
case DW_FORM_exprloc:
diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
index 44a24f2756ad..ab0c37beeac9 100644
--- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
+++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -169,7 +169,7 @@ struct DWARFMappedHash
{
if (return_implementation_only_if_available)
{
- // We found the one true definiton for this class, so
+ // We found the one true definition for this class, so
// only return that
die_offsets.clear();
die_offsets.push_back (die_info_array[i].offset);
@@ -388,7 +388,7 @@ struct DWARFMappedHash
}
size_t
- GetMinumumHashDataByteSize () const
+ GetMinimumHashDataByteSize () const
{
return min_hash_data_byte_size;
}
@@ -465,7 +465,7 @@ struct DWARFMappedHash
break;
default:
- // We can always skip atomes we don't know about
+ // We can always skip atoms we don't know about
break;
}
}
@@ -651,11 +651,11 @@ struct DWARFMappedHash
}
const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
- const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize();
+ const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
{
// We have at least one HashData entry, and we have enough
- // data to parse at leats "count" HashData enties.
+ // data to parse at least "count" HashData entries.
// First make sure the entire C string matches...
const bool match = strcmp (name, strp_cstr) == 0;
@@ -678,7 +678,7 @@ struct DWARFMappedHash
DIEInfo die_info;
if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
{
- // Only happend the HashData if the string matched...
+ // Only happened if the HashData of the string matched...
if (match)
pair.value.push_back (die_info);
}
@@ -724,7 +724,7 @@ struct DWARFMappedHash
return eResultError;
const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
- const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize();
+ const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
{
const bool match = regex.Execute(strp_cstr);
@@ -747,7 +747,7 @@ struct DWARFMappedHash
DIEInfo die_info;
if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
{
- // Only happend the HashData if the string matched...
+ // Only happened if the HashData of the string matched...
if (match)
pair.value.push_back (die_info);
}
diff --git a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
index c9ffa9ec781f..fbbc03c94625 100644
--- a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
@@ -18,7 +18,7 @@ using namespace lldb;
using namespace lldb_private;
-// when the one and only logging channel is abled, then this will be non NULL.
+// when the one and only logging channel is enabled, then this will be non NULL.
static LogChannelDWARF* g_log_channel = NULL;
LogChannelDWARF::LogChannelDWARF () :
@@ -103,6 +103,7 @@ LogChannelDWARF::Disable (const char **categories, Stream *feedback_strm)
else if (::strcasecmp (arg, "lookups") == 0) flag_bits &= ~DWARF_LOG_LOOKUPS;
else if (::strcasecmp (arg, "map") == 0) flag_bits &= ~DWARF_LOG_DEBUG_MAP;
else if (::strcasecmp (arg, "default") == 0) flag_bits &= ~DWARF_LOG_DEFAULT;
+ else if (::strcasecmp (arg, "verbose") == 0) flag_bits &= ~DWARF_LOG_VERBOSE;
else if (::strncasecmp(arg, "comp", 4) == 0) flag_bits &= ~DWARF_LOG_TYPE_COMPLETION;
else
{
@@ -151,6 +152,7 @@ LogChannelDWARF::Enable
else if (::strcasecmp (arg, "lookups") == 0) flag_bits |= DWARF_LOG_LOOKUPS;
else if (::strcasecmp (arg, "map") == 0) flag_bits |= DWARF_LOG_DEBUG_MAP;
else if (::strcasecmp (arg, "default") == 0) flag_bits |= DWARF_LOG_DEFAULT;
+ else if (::strcasecmp (arg, "verbose") == 0) flag_bits |= DWARF_LOG_VERBOSE;
else if (::strncasecmp(arg, "comp", 4) == 0) flag_bits |= DWARF_LOG_TYPE_COMPLETION;
else
{
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index c1aecfe8eb62..842260dbc3ba 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -66,6 +66,9 @@
#include <map>
+#include <ctype.h>
+#include <string.h>
+
//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
@@ -110,7 +113,35 @@ DW_ACCESS_to_AccessType (uint32_t dwarf_accessibility)
return eAccessNone;
}
-#if defined(LLDB_CONFIGURATION_DEBUG) or defined(LLDB_CONFIGURATION_RELEASE)
+static const char*
+removeHostnameFromPathname(const char* path_from_dwarf)
+{
+ if (!path_from_dwarf || !path_from_dwarf[0])
+ {
+ return path_from_dwarf;
+ }
+
+ const char *colon_pos = strchr(path_from_dwarf, ':');
+ if (!colon_pos)
+ {
+ return path_from_dwarf;
+ }
+
+ // check whether we have a windows path, and so the first character
+ // is a drive-letter not a hostname.
+ if (
+ colon_pos == path_from_dwarf + 1 &&
+ isalpha(*path_from_dwarf) &&
+ strlen(path_from_dwarf) > 2 &&
+ '\\' == path_from_dwarf[2])
+ {
+ return path_from_dwarf;
+ }
+
+ return colon_pos + 1;
+}
+
+#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
class DIEStack
{
@@ -525,7 +556,7 @@ SymbolFileDWARF::GetClangASTContext ()
if (!m_is_external_ast_source)
{
m_is_external_ast_source = true;
- llvm::OwningPtr<clang::ExternalASTSource> ast_source_ap (
+ llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap (
new ClangExternalASTSourceCallbacks (SymbolFileDWARF::CompleteTagDecl,
SymbolFileDWARF::CompleteObjCInterfaceDecl,
SymbolFileDWARF::FindExternalVisibleDeclsByName,
@@ -829,7 +860,8 @@ SymbolFileDWARF::DebugInfo()
{
if (m_info.get() == NULL)
{
- Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
+ Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p",
+ __PRETTY_FUNCTION__, static_cast<void*>(this));
if (get_debug_info_data().GetByteSize() > 0)
{
m_info.reset(new DWARFDebugInfo());
@@ -879,7 +911,8 @@ SymbolFileDWARF::DebugRanges()
{
if (m_ranges.get() == NULL)
{
- Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
+ Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p",
+ __PRETTY_FUNCTION__, static_cast<void*>(this));
if (get_debug_ranges_data().GetByteSize() > 0)
{
m_ranges.reset(new DWARFDebugRanges());
@@ -943,7 +976,11 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)
}
else
{
+ // DWARF2/3 suggests the form hostname:pathname for compilation directory.
+ // Remove the host part if present.
+ cu_comp_dir = removeHostnameFromPathname(cu_comp_dir);
std::string fullpath(cu_comp_dir);
+
if (*fullpath.rbegin() != '/')
fullpath += '/';
fullpath += cu_die_name;
@@ -1170,6 +1207,11 @@ SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpec
if (cu_die)
{
const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_comp_dir, NULL);
+
+ // DWARF2/3 suggests the form hostname:pathname for compilation directory.
+ // Remove the host part if present.
+ cu_comp_dir = removeHostnameFromPathname(cu_comp_dir);
+
dw_offset_t stmt_list = cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET);
// All file indexes in DWARF are one based and a file of index zero is
@@ -1983,7 +2025,7 @@ SymbolFileDWARF::ParseChildMembers
const uint64_t word_width = 32;
// Objective-C has invalid DW_AT_bit_offset values in older versions
- // of clang, so we have to be careful and only insert unnammed bitfields
+ // of clang, so we have to be careful and only insert unnamed bitfields
// if we have a new enough clang.
bool detect_unnamed_bitfields = true;
@@ -2380,7 +2422,6 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
// The type will get resolved when all of the calls to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition
// are done.
m_forward_decl_clang_type_to_die.erase (clang_type_no_qualifiers.GetOpaqueQualType());
-
// Disable external storage for this type so we don't get anymore
// clang::ExternalASTSource queries for this type.
@@ -2395,14 +2436,11 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
if (log)
- {
GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log,
"0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...",
MakeUserID(die->GetOffset()),
DW_TAG_value_to_name(tag),
type->GetName().AsCString());
-
- }
assert (clang_type);
DWARFDebugInfoEntry::Attributes attributes;
@@ -2413,11 +2451,10 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
case DW_TAG_class_type:
{
LayoutInfo layout_info;
-
+
{
if (die->HasChildren())
{
-
LanguageType class_language = eLanguageTypeUnknown;
if (clang_type.IsObjCObjectOrInterfaceType())
{
@@ -2426,7 +2463,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
// the class is created.
clang_type.StartTagDeclarationDefinition ();
}
-
+
int tag_decl_kind = -1;
AccessType default_accessibility = eAccessNone;
if (tag == DW_TAG_structure_type)
@@ -2444,14 +2481,14 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
tag_decl_kind = clang::TTK_Class;
default_accessibility = eAccessPrivate;
}
-
+
SymbolContext sc(GetCompUnitForDWARFCompUnit(dwarf_cu));
std::vector<clang::CXXBaseSpecifier *> base_classes;
std::vector<int> member_accessibilities;
bool is_a_class = false;
// Parse members and base classes first
DWARFDIECollection member_function_dies;
-
+
DelayedPropertyList delayed_properties;
ParseChildMembers (sc,
dwarf_cu,
@@ -2465,7 +2502,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
default_accessibility,
is_a_class,
layout_info);
-
+
// Now parse any methods if there were any...
size_t num_functions = member_function_dies.Size();
if (num_functions > 0)
@@ -2475,13 +2512,12 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
ResolveType(dwarf_cu, member_function_dies.GetDIEPtrAtIndex(i));
}
}
-
+
if (class_language == eLanguageTypeObjC)
{
ConstString class_name (clang_type.GetTypeName());
if (class_name)
{
-
DIEArray method_die_offsets;
if (m_using_apple_tables)
{
@@ -2492,21 +2528,21 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
{
if (!m_indexed)
Index ();
-
+
m_objc_class_selectors_index.Find (class_name, method_die_offsets);
}
-
+
if (!method_die_offsets.empty())
{
DWARFDebugInfo* debug_info = DebugInfo();
-
+
DWARFCompileUnit* method_cu = NULL;
const size_t num_matches = method_die_offsets.size();
for (size_t i=0; i<num_matches; ++i)
{
const dw_offset_t die_offset = method_die_offsets[i];
DWARFDebugInfoEntry *method_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &method_cu);
-
+
if (method_die)
ResolveType (method_cu, method_die);
else
@@ -2519,14 +2555,14 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
}
}
}
-
+
for (DelayedPropertyList::iterator pi = delayed_properties.begin(), pe = delayed_properties.end();
pi != pe;
++pi)
pi->Finalize();
}
}
-
+
// If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
// need to tell the clang type it is actually a class.
if (class_language != eLanguageTypeObjC)
@@ -2534,7 +2570,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
if (is_a_class && tag_decl_kind != clang::TTK_Class)
clang_type.SetTagTypeKind (clang::TTK_Class);
}
-
+
// Since DW_TAG_structure_type gets used for both classes
// and structures, we may need to set any DW_TAG_member
// fields to have a "private" access if none was specified.
@@ -2553,7 +2589,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
&member_accessibilities.front(),
member_accessibilities.size());
}
-
+
if (!base_classes.empty())
{
// Make sure all base classes refer to complete types and not
@@ -2580,7 +2616,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
// is complete. If we don't do this, clang will crash when we
// call setBases() inside of "clang_type.SetBaseClassesForClassType()"
// below. Since we provide layout assistance, all ivars in this
- // class and other classe will be fine, this is the best we can do
+ // class and other classes will be fine, this is the best we can do
// short of crashing.
base_class_type.StartTagDeclarationDefinition ();
base_class_type.CompleteTagDeclarationDefinition ();
@@ -2589,7 +2625,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
}
clang_type.SetBaseClassesForClassType (&base_classes.front(),
base_classes.size());
-
+
// Clang will copy each CXXBaseSpecifier in "base_classes"
// so we have to free them all.
ClangASTType::DeleteBaseClassSpecifiers (&base_classes.front(),
@@ -2597,10 +2633,10 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
}
}
}
-
+
clang_type.BuildIndirectFields ();
clang_type.CompleteTagDeclarationDefinition ();
-
+
if (!layout_info.field_offsets.empty() ||
!layout_info.base_offsets.empty() ||
!layout_info.vbase_offsets.empty() )
@@ -2609,7 +2645,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
layout_info.bit_size = type->GetByteSize() * 8;
if (layout_info.bit_size == 0)
layout_info.bit_size = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_byte_size, 0) * 8;
-
+
clang::CXXRecordDecl *record_decl = clang_type.GetAsCXXRecordDecl();
if (record_decl)
{
@@ -2617,14 +2653,14 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
{
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) caching layout info for record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u], base_offsets[%u], vbase_offsets[%u])",
- clang_type.GetOpaqueQualType(),
- record_decl,
+ static_cast<void*>(clang_type.GetOpaqueQualType()),
+ static_cast<void*>(record_decl),
layout_info.bit_size,
layout_info.alignment,
- (uint32_t)layout_info.field_offsets.size(),
- (uint32_t)layout_info.base_offsets.size(),
- (uint32_t)layout_info.vbase_offsets.size());
-
+ static_cast<uint32_t>(layout_info.field_offsets.size()),
+ static_cast<uint32_t>(layout_info.base_offsets.size()),
+ static_cast<uint32_t>(layout_info.vbase_offsets.size()));
+
uint32_t idx;
{
llvm::DenseMap <const clang::FieldDecl *, uint64_t>::const_iterator pos, end = layout_info.field_offsets.end();
@@ -2632,13 +2668,13 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
{
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) field[%u] = { bit_offset=%u, name='%s' }",
- clang_type.GetOpaqueQualType(),
+ static_cast<void*>(clang_type.GetOpaqueQualType()),
idx,
- (uint32_t)pos->second,
+ static_cast<uint32_t>(pos->second),
pos->first->getNameAsString().c_str());
}
}
-
+
{
llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator base_pos, base_end = layout_info.base_offsets.end();
for (idx = 0, base_pos = layout_info.base_offsets.begin(); base_pos != base_end; ++base_pos, ++idx)
@@ -2657,9 +2693,9 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
{
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) vbase[%u] = { byte_offset=%u, name='%s' }",
- clang_type.GetOpaqueQualType(),
+ static_cast<void*>(clang_type.GetOpaqueQualType()),
idx,
- (uint32_t)vbase_pos->second.getQuantity(),
+ static_cast<uint32_t>(vbase_pos->second.getQuantity()),
vbase_pos->first->getNameAsString().c_str());
}
}
@@ -2755,9 +2791,8 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_
{
Timer scoped_timer(__PRETTY_FUNCTION__,
"SymbolFileDWARF::ResolveSymbolContext (so_addr = { section = %p, offset = 0x%" PRIx64 " }, resolve_scope = 0x%8.8x)",
- so_addr.GetSection().get(),
- so_addr.GetOffset(),
- resolve_scope);
+ static_cast<void*>(so_addr.GetSection().get()),
+ so_addr.GetOffset(), resolve_scope);
uint32_t resolved = 0;
if (resolve_scope & ( eSymbolContextCompUnit |
eSymbolContextFunction |
@@ -3086,7 +3121,7 @@ SymbolFileDWARF::DIEIsInNamespace (const ClangNamespaceDecl *namespace_decl,
DWARFCompileUnit* cu,
const DWARFDebugInfoEntry* die)
{
- // No namespace specified, so the answesr i
+ // No namespace specified, so the answer is
if (namespace_decl == NULL)
return true;
@@ -3116,7 +3151,7 @@ SymbolFileDWARF::DIEIsInNamespace (const ClangNamespaceDecl *namespace_decl,
{
// We have a namespace_decl that was not NULL but it contained
// a NULL "clang::NamespaceDecl", so this means the global namespace
- // So as long the the contained decl context DIE isn't a namespace
+ // So as long the contained decl context DIE isn't a namespace
// we should be ok.
if (decl_ctx_die->Tag() != DW_TAG_namespace)
return true;
@@ -3134,18 +3169,15 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
if (log)
- {
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables)",
name.GetCString(),
- namespace_decl,
- append,
- max_matches);
- }
-
+ static_cast<const void*>(namespace_decl),
+ append, max_matches);
+
if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
return 0;
-
+
DWARFDebugInfo* info = DebugInfo();
if (info == NULL)
return 0;
@@ -3159,7 +3191,7 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
const uint32_t original_size = variables.GetSize();
DIEArray die_offsets;
-
+
if (m_using_apple_tables)
{
if (m_apple_names_ap.get())
@@ -3167,10 +3199,10 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
const char *name_cstr = name.GetCString();
const char *base_name_start;
const char *base_name_end = NULL;
-
+
if (!CPPLanguageRuntime::StripNamespacesFromVariableName(name_cstr, base_name_start, base_name_end))
base_name_start = name_cstr;
-
+
m_apple_names_ap->FindByName (base_name_start, die_offsets);
}
}
@@ -3182,14 +3214,14 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
m_global_index.Find (name, die_offsets);
}
-
+
const size_t num_die_matches = die_offsets.size();
if (num_die_matches)
{
SymbolContext sc;
sc.module_sp = m_obj_file->GetModule();
assert (sc.module_sp);
-
+
DWARFDebugInfo* debug_info = DebugInfo();
DWARFCompileUnit* dwarf_cu = NULL;
const DWARFDebugInfoEntry* die = NULL;
@@ -3209,11 +3241,11 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
case DW_TAG_try_block:
case DW_TAG_catch_block:
break;
-
+
case DW_TAG_variable:
{
sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
-
+
if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
continue;
@@ -3242,10 +3274,9 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
{
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables) => %u",
- name.GetCString(),
- namespace_decl,
- append,
- max_matches,
+ name.GetCString(),
+ static_cast<const void*>(namespace_decl),
+ append, max_matches,
num_matches);
}
return num_matches;
@@ -3255,13 +3286,12 @@ uint32_t
SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
{
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
-
+
if (log)
{
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::FindGlobalVariables (regex=\"%s\", append=%u, max_matches=%u, variables)",
- regex.GetText(),
- append,
+ regex.GetText(), append,
max_matches);
}
@@ -3959,38 +3989,32 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
return 0;
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
-
+
if (log)
{
if (namespace_decl)
- {
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(%p) \"%s\", append=%u, max_matches=%u, type_list)",
name.GetCString(),
- namespace_decl->GetNamespaceDecl(),
+ static_cast<void*>(namespace_decl->GetNamespaceDecl()),
namespace_decl->GetQualifiedName().c_str(),
- append,
- max_matches);
- }
+ append, max_matches);
else
- {
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list)",
- name.GetCString(),
- append,
+ name.GetCString(), append,
max_matches);
- }
}
// If we aren't appending the results to this list, then clear the list
if (!append)
types.Clear();
-
+
if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
return 0;
DIEArray die_offsets;
-
+
if (m_using_apple_tables)
{
if (m_apple_types_ap.get())
@@ -4003,10 +4027,10 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
{
if (!m_indexed)
Index ();
-
+
m_type_index.Find (name, die_offsets);
}
-
+
const size_t num_die_matches = die_offsets.size();
if (num_die_matches)
@@ -4024,7 +4048,7 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
{
if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
continue;
-
+
Type *matching_type = ResolveType (dwarf_cu, die);
if (matching_type)
{
@@ -4052,10 +4076,9 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(%p) \"%s\", append=%u, max_matches=%u, type_list) => %u",
name.GetCString(),
- namespace_decl->GetNamespaceDecl(),
+ static_cast<void*>(namespace_decl->GetNamespaceDecl()),
namespace_decl->GetQualifiedName().c_str(),
- append,
- max_matches,
+ append, max_matches,
num_matches);
}
else
@@ -4063,8 +4086,7 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list) => %u",
name.GetCString(),
- append,
- max_matches,
+ append, max_matches,
num_matches);
}
}
@@ -4156,7 +4178,7 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => clang::NamespaceDecl(%p) \"%s\"",
name.GetCString(),
- namespace_decl.GetNamespaceDecl(),
+ static_cast<const void*>(namespace_decl.GetNamespaceDecl()),
namespace_decl.GetQualifiedName().c_str());
}
@@ -4203,8 +4225,8 @@ SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc,
TypeList* type_list,
std::vector<ClangASTType>& function_param_types,
std::vector<clang::ParmVarDecl*>& function_param_decls,
- unsigned &type_quals,
- ClangASTContext::TemplateParameterInfos &template_param_infos)
+ unsigned &type_quals) // ,
+ // ClangASTContext::TemplateParameterInfos &template_param_infos))
{
if (parent_die == NULL)
return 0;
@@ -4357,7 +4379,11 @@ SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc,
case DW_TAG_template_type_parameter:
case DW_TAG_template_value_parameter:
- ParseTemplateDIE (dwarf_cu, die,template_param_infos);
+ // The one caller of this was never using the template_param_infos,
+ // and the local variable was taking up a large amount of stack space
+ // in SymbolFileDWARF::ParseType() so this was removed. If we ever need
+ // the template params back, we can add them back.
+ // ParseTemplateDIE (dwarf_cu, die, template_param_infos);
break;
default:
@@ -4618,20 +4644,20 @@ SymbolFileDWARF::ResolveNamespaceDIE (DWARFCompileUnit *dwarf_cu, const DWARFDeb
{
GetObjectFile()->GetModule()->LogMessage (log,
"ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace with DW_AT_name(\"%s\") => clang::NamespaceDecl *%p (original = %p)",
- GetClangASTContext().getASTContext(),
+ static_cast<void*>(GetClangASTContext().getASTContext()),
MakeUserID(die->GetOffset()),
namespace_name,
- namespace_decl,
- namespace_decl->getOriginalNamespace());
+ static_cast<void*>(namespace_decl),
+ static_cast<void*>(namespace_decl->getOriginalNamespace()));
}
else
{
GetObjectFile()->GetModule()->LogMessage (log,
"ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p)",
- GetClangASTContext().getASTContext(),
+ static_cast<void*>(GetClangASTContext().getASTContext()),
MakeUserID(die->GetOffset()),
- namespace_decl,
- namespace_decl->getOriginalNamespace());
+ static_cast<void*>(namespace_decl),
+ static_cast<void*>(namespace_decl->getOriginalNamespace()));
}
}
@@ -4982,7 +5008,7 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn
if (count1 != count2)
return false;
- // Make sure the DW_TAG values match all the way back up the the
+ // Make sure the DW_TAG values match all the way back up the
// compile unit. If they don't, then we are done.
const DWARFDebugInfoEntry *decl_ctx_die1;
const DWARFDebugInfoEntry *decl_ctx_die2;
@@ -5084,7 +5110,7 @@ SymbolFileDWARF::FindDefinitionTypeForDIE (DWARFCompileUnit* cu,
GetObjectFile()->GetModule()->LogMessage (log,"FindByNameAndTagAndQualifiedNameHash()");
m_apple_types_ap->FindByNameAndTagAndQualifiedNameHash (type_name.GetCString(), die->Tag(), qualified_name_hash, die_offsets);
}
- else if (has_tag > 1)
+ else if (has_tag)
{
if (log)
GetObjectFile()->GetModule()->LogMessage (log,"FindByNameAndTag()");
@@ -5388,7 +5414,7 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
const DWARFDebugInfoEntry *src_class_die,
DWARFCompileUnit* dst_cu,
const DWARFDebugInfoEntry *dst_class_die,
- llvm::SmallVectorImpl <const DWARFDebugInfoEntry *> &failures)
+ DWARFDIECollection &failures)
{
if (!class_type || !src_cu || !src_class_die || !dst_cu || !dst_class_die)
return false;
@@ -5456,7 +5482,7 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
// Is everything kosher so we can go through the members at top speed?
bool fast_path = true;
-
+
if (src_size != dst_size)
{
if (src_size != 0 && dst_size != 0)
@@ -5468,12 +5494,12 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
src_size,
dst_size);
}
-
+
fast_path = false;
}
uint32_t idx;
-
+
if (fast_path)
{
for (idx = 0; idx < src_size; ++idx)
@@ -5493,10 +5519,10 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
DW_TAG_value_to_name(src_die->Tag()));
fast_path = false;
}
-
+
const char *src_name = src_die->GetMangledName (src_symfile, src_cu);
const char *dst_name = dst_die->GetMangledName (this, dst_cu);
-
+
// Make sure the names match
if (src_name == dst_name || (strcmp (src_name, dst_name) == 0))
continue;
@@ -5509,7 +5535,7 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
src_name,
dst_die->GetOffset(),
dst_name);
-
+
fast_path = false;
}
}
@@ -5523,25 +5549,31 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
{
src_die = src_name_to_die.GetValueAtIndexUnchecked (idx);
dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx);
-
+
clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die];
if (src_decl_ctx)
{
if (log)
- log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", src_decl_ctx, src_die->GetOffset(), dst_die->GetOffset());
+ log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_decl_ctx),
+ src_die->GetOffset(), dst_die->GetOffset());
LinkDeclContextToDIE (src_decl_ctx, dst_die);
}
else
{
if (log)
- log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
+ log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found",
+ src_die->GetOffset(), dst_die->GetOffset());
}
-
+
Type *src_child_type = m_die_to_type[src_die];
if (src_child_type)
{
if (log)
- log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", src_child_type, src_child_type->GetID(), src_die->GetOffset(), dst_die->GetOffset());
+ log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_child_type),
+ src_child_type->GetID(),
+ src_die->GetOffset(), dst_die->GetOffset());
m_die_to_type[dst_die] = src_child_type;
}
else
@@ -5556,24 +5588,27 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
// We must do this slowly. For each member of the destination, look
// up a member in the source with the same name, check its tag, and
// unique them if everything matches up. Report failures.
-
+
if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty())
{
src_name_to_die.Sort();
-
+
for (idx = 0; idx < dst_size; ++idx)
{
const char *dst_name = dst_name_to_die.GetCStringAtIndex(idx);
dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);
src_die = src_name_to_die.Find(dst_name, NULL);
-
+
if (src_die && (src_die->Tag() == dst_die->Tag()))
{
clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die];
if (src_decl_ctx)
{
if (log)
- log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", src_decl_ctx, src_die->GetOffset(), dst_die->GetOffset());
+ log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_decl_ctx),
+ src_die->GetOffset(),
+ dst_die->GetOffset());
LinkDeclContextToDIE (src_decl_ctx, dst_die);
}
else
@@ -5581,12 +5616,16 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
if (log)
log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
}
-
+
Type *src_child_type = m_die_to_type[src_die];
if (src_child_type)
{
if (log)
- log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", src_child_type, src_child_type->GetID(), src_die->GetOffset(), dst_die->GetOffset());
+ log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_child_type),
+ src_child_type->GetID(),
+ src_die->GetOffset(),
+ dst_die->GetOffset());
m_die_to_type[dst_die] = src_child_type;
}
else
@@ -5600,7 +5639,7 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
if (log)
log->Printf ("warning: couldn't find a match for 0x%8.8x", dst_die->GetOffset());
- failures.push_back(dst_die);
+ failures.Append(dst_die);
}
}
}
@@ -5614,13 +5653,13 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
if (src_size_artificial && dst_size_artificial)
{
dst_name_to_die_artificial.Sort();
-
+
for (idx = 0; idx < src_size_artificial; ++idx)
{
const char *src_name_artificial = src_name_to_die_artificial.GetCStringAtIndex(idx);
src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked (idx);
dst_die = dst_name_to_die_artificial.Find(src_name_artificial, NULL);
-
+
if (dst_die)
{
// Both classes have the artificial types, link them
@@ -5628,7 +5667,9 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
if (src_decl_ctx)
{
if (log)
- log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", src_decl_ctx, src_die->GetOffset(), dst_die->GetOffset());
+ log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_decl_ctx),
+ src_die->GetOffset(), dst_die->GetOffset());
LinkDeclContextToDIE (src_decl_ctx, dst_die);
}
else
@@ -5636,12 +5677,15 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
if (log)
log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
}
-
+
Type *src_child_type = m_die_to_type[src_die];
if (src_child_type)
{
if (log)
- log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", src_child_type, src_child_type->GetID(), src_die->GetOffset(), dst_die->GetOffset());
+ log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_child_type),
+ src_child_type->GetID(),
+ src_die->GetOffset(), dst_die->GetOffset());
m_die_to_type[dst_die] = src_child_type;
}
else
@@ -5662,11 +5706,11 @@ SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
if (log)
log->Printf ("warning: need to create artificial method for 0x%8.8x for method '%s'", dst_die->GetOffset(), dst_name_artificial);
- failures.push_back(dst_die);
+ failures.Append(dst_die);
}
}
- return (failures.size() != 0);
+ return (failures.Size() != 0);
}
TypeSP
@@ -5677,7 +5721,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
if (type_is_new_ptr)
*type_is_new_ptr = false;
-#if defined(LLDB_CONFIGURATION_DEBUG) or defined(LLDB_CONFIGURATION_RELEASE)
+#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
static DIEStack g_die_stack;
DIEStack::ScopedPopper scoped_die_logger(g_die_stack);
#endif
@@ -5690,15 +5734,15 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
{
const DWARFDebugInfoEntry *context_die;
clang::DeclContext *context = GetClangDeclContextContainingDIE (dwarf_cu, die, &context_die);
-
+
GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')",
- die->GetOffset(),
- context,
- context_die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, dwarf_cu));
-
-#if defined(LLDB_CONFIGURATION_DEBUG) or defined(LLDB_CONFIGURATION_RELEASE)
+ die->GetOffset(),
+ static_cast<void*>(context),
+ context_die->GetOffset(),
+ DW_TAG_value_to_name(die->Tag()),
+ die->GetName(this, dwarf_cu));
+
+#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
scoped_die_logger.Push (dwarf_cu, die);
g_die_stack.LogDIEs(log, this);
#endif
@@ -5712,7 +5756,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
// GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData());
//
// }
-
+
Type *type_ptr = m_die_to_type.lookup (die);
TypeList* type_list = GetTypeList();
if (type_ptr == NULL)
@@ -5733,7 +5777,8 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
ClangASTType clang_type;
-
+ DWARFFormValue form_value;
+
dw_attr_t attr;
switch (tag)
@@ -5761,7 +5806,6 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
for (i=0; i<num_attributes; ++i)
{
attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
{
switch (attr)
@@ -5770,7 +5814,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
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:
-
+
type_name_cstr = form_value.AsCString(&get_debug_str_data());
// Work around a bug in llvm-gcc where they give a name to a reference type which doesn't
// include the "&"...
@@ -5829,7 +5873,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL)
{
bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus);
-
+
if (translation_unit_is_objc)
{
if (type_name_cstr != NULL)
@@ -5837,7 +5881,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
static ConstString g_objc_type_name_id("id");
static ConstString g_objc_type_name_Class("Class");
static ConstString g_objc_type_name_selector("SEL");
-
+
if (type_name_const_str == g_objc_type_name_id)
{
if (log)
@@ -5879,11 +5923,11 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid != LLDB_INVALID_UID)
{
// Clang sometimes erroneously emits id as objc_object*. In that case we fix up the type to "id".
-
+
DWARFDebugInfoEntry* encoding_die = dwarf_cu->GetDIEPtr(encoding_uid);
-
+
if (encoding_die && encoding_die->Tag() == DW_TAG_structure_type)
- {
+ {
if (const char *struct_name = encoding_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL))
{
if (!strcmp(struct_name, "objc_object"))
@@ -5903,7 +5947,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
}
}
}
-
+
type_sp.reset( new Type (MakeUserID(die->GetOffset()),
this,
type_name_const_str,
@@ -5914,7 +5958,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
&decl,
clang_type,
resolve_state));
-
+
m_die_to_type[die] = type_sp.get();
// Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false);
@@ -5946,7 +5990,6 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
for (i=0; i<num_attributes; ++i)
{
attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
{
switch (attr)
@@ -5996,7 +6039,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
case DW_AT_APPLE_objc_complete_type:
is_complete_objc_class = form_value.Signed();
break;
-
+
case DW_AT_allocated:
case DW_AT_associated:
case DW_AT_data_location:
@@ -6010,8 +6053,11 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
}
}
}
-
- UniqueDWARFASTType unique_ast_entry;
+
+ // UniqueDWARFASTType is large, so don't create a local variables on the
+ // stack, put it on the heap. This function is often called recursively
+ // and clang isn't good and sharing the stack space for variables in different blocks.
+ std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType());
// Only try and unique the type if it has a name.
if (type_name_const_str &&
@@ -6021,21 +6067,21 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
die,
decl,
byte_size_valid ? byte_size : -1,
- unique_ast_entry))
+ *unique_ast_entry_ap))
{
// We have already parsed this type or from another
// compile unit. GCC loves to use the "one definition
// rule" which can result in multiple definitions
// of the same class over and over in each compile
// unit.
- type_sp = unique_ast_entry.m_type_sp;
+ type_sp = unique_ast_entry_ap->m_type_sp;
if (type_sp)
{
m_die_to_type[die] = type_sp.get();
return type_sp;
}
}
-
+
DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
int tag_decl_kind = -1;
@@ -6055,7 +6101,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
tag_decl_kind = clang::TTK_Class;
default_accessibility = eAccessPrivate;
}
-
+
if (byte_size_valid && byte_size == 0 && type_name_cstr &&
die->HasChildren() == false &&
sc.comp_unit->GetLanguage() == eLanguageTypeObjC)
@@ -6093,20 +6139,20 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
// else...
type_sp = m_debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true);
}
-
+
if (type_sp)
{
if (log)
{
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an incomplete objc type, complete type is 0x%8.8" PRIx64,
- this,
+ static_cast<void*>(this),
die->GetOffset(),
DW_TAG_value_to_name(tag),
type_name_cstr,
type_sp->GetID());
}
-
+
// We found a real definition for this type elsewhere
// so lets use it and cache the fact that we found
// a complete type for this die
@@ -6115,7 +6161,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
}
}
}
-
+
if (is_forward_declaration)
{
@@ -6128,12 +6174,12 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
{
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, trying to find complete type",
- this,
+ static_cast<void*>(this),
die->GetOffset(),
DW_TAG_value_to_name(tag),
type_name_cstr);
}
-
+
DWARFDeclContext die_decl_ctx;
die->GetDWARFDeclContext(this, dwarf_cu, die_decl_ctx);
@@ -6154,7 +6200,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
{
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8" PRIx64,
- this,
+ static_cast<void*>(this),
die->GetOffset(),
DW_TAG_value_to_name(tag),
type_name_cstr,
@@ -6174,12 +6220,12 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
if (!clang_type)
{
const DWARFDebugInfoEntry *decl_ctx_die;
-
+
clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die);
if (accessibility == eAccessNone && decl_ctx)
{
// Check the decl context that contains this class/struct/union.
- // If it is a class we must give it an accessability.
+ // If it is a class we must give it an accessibility.
const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind();
if (DeclKindIsCXXClass (containing_decl_kind))
accessibility = default_accessibility;
@@ -6199,14 +6245,14 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
type_name_cstr,
tag_decl_kind,
template_param_infos);
-
+
clang::ClassTemplateSpecializationDecl *class_specialization_decl = ast.CreateClassTemplateSpecializationDecl (decl_ctx,
class_template_decl,
tag_decl_kind,
template_param_infos);
clang_type = ast.CreateClassTemplateSpecializationType (class_specialization_decl);
clang_type_was_created = true;
-
+
GetClangASTContext().SetMetadata (class_template_decl, metadata);
GetClangASTContext().SetMetadata (class_specialization_decl, metadata);
}
@@ -6238,22 +6284,22 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
&decl,
clang_type,
Type::eResolveStateForward));
-
+
type_sp->SetIsCompleteObjCClass(is_complete_objc_class);
// Add our type to the unique type map so we don't
// end up creating many copies of the same type over
// and over in the ASTContext for our module
- unique_ast_entry.m_type_sp = type_sp;
- unique_ast_entry.m_symfile = this;
- unique_ast_entry.m_cu = dwarf_cu;
- unique_ast_entry.m_die = die;
- unique_ast_entry.m_declaration = decl;
- unique_ast_entry.m_byte_size = byte_size;
+ unique_ast_entry_ap->m_type_sp = type_sp;
+ unique_ast_entry_ap->m_symfile = this;
+ unique_ast_entry_ap->m_cu = dwarf_cu;
+ unique_ast_entry_ap->m_die = die;
+ unique_ast_entry_ap->m_declaration = decl;
+ unique_ast_entry_ap->m_byte_size = byte_size;
GetUniqueDWARFASTTypeMap().Insert (type_name_const_str,
- unique_ast_entry);
-
+ *unique_ast_entry_ap);
+
if (is_forward_declaration && die->HasChildren())
{
// Check to see if the DIE actually has a definition, some version of GCC will
@@ -6294,32 +6340,25 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
// No children for this struct/union/class, lets finish it
clang_type.StartTagDeclarationDefinition ();
clang_type.CompleteTagDeclarationDefinition ();
-
+
if (tag == DW_TAG_structure_type) // this only applies in C
{
clang::RecordDecl *record_decl = clang_type.GetAsRecordDecl();
-
+
if (record_decl)
- {
- LayoutInfo layout_info;
-
- layout_info.alignment = 0;
- layout_info.bit_size = 0;
-
- m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info));
- }
+ m_record_decl_to_layout_map.insert(std::make_pair(record_decl, LayoutInfo()));
}
}
else if (clang_type_was_created)
{
// Start the definition if the class is not objective C since
// the underlying decls respond to isCompleteDefinition(). Objective
- // C decls dont' respond to isCompleteDefinition() so we can't
- // start the declaration definition right away. For C++ classs/union/structs
+ // C decls don't respond to isCompleteDefinition() so we can't
+ // start the declaration definition right away. For C++ class/union/structs
// we want to start the definition in case the class is needed as the
// declaration context for a contained class or type without the need
// to complete that type..
-
+
if (class_language != eLanguageTypeObjC &&
class_language != eLanguageTypeObjC_plus_plus)
clang_type.StartTagDeclarationDefinition ();
@@ -6334,7 +6373,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
clang_type.SetHasExternalStorage (true);
}
}
-
+
}
break;
@@ -6353,7 +6392,6 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
for (i=0; i<num_attributes; ++i)
{
attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
{
switch (attr)
@@ -6397,12 +6435,12 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
if (enumerator_type)
enumerator_clang_type = enumerator_type->GetClangFullType();
}
-
+
if (!enumerator_clang_type)
enumerator_clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL,
DW_ATE_signed,
byte_size * 8);
-
+
clang_type = ast.CreateEnumerationType (type_name_cstr,
GetClangDeclContextContainingDIE (dwarf_cu, die, NULL),
decl,
@@ -6414,7 +6452,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
}
LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die);
-
+
type_sp.reset( new Type (MakeUserID(die->GetOffset()),
this,
type_name_const_str,
@@ -6469,7 +6507,6 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
for (i=0; i<num_attributes; ++i)
{
attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
{
switch (attr)
@@ -6491,7 +6528,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
case DW_AT_virtuality: is_virtual = form_value.Boolean(); break;
case DW_AT_explicit: is_explicit = form_value.Boolean(); break;
case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
-
+
case DW_AT_external:
if (form_value.Unsigned())
@@ -6554,12 +6591,12 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
object_pointer_name.assign(s.GetData());
}
}
-
+
DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
ClangASTType return_clang_type;
Type *func_type = NULL;
-
+
if (type_die_offset != DW_INVALID_OFFSET)
func_type = ResolveTypeUID(type_die_offset);
@@ -6573,18 +6610,17 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
std::vector<clang::ParmVarDecl*> function_param_decls;
// Parse the function children for the parameters
-
+
const DWARFDebugInfoEntry *decl_ctx_die = NULL;
clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die);
const clang::Decl::Kind containing_decl_kind = containing_decl_ctx->getDeclKind();
const bool is_cxx_method = DeclKindIsCXXClass (containing_decl_kind);
// Start off static. This will be set to false in ParseChildParameters(...)
- // if we find a "this" paramters as the first parameter
+ // if we find a "this" parameters as the first parameter
if (is_cxx_method)
is_static = true;
- ClangASTContext::TemplateParameterInfos template_param_infos;
-
+
if (die->HasChildren())
{
bool skip_artificial = true;
@@ -6598,8 +6634,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
type_list,
function_param_types,
function_param_decls,
- type_quals,
- template_param_infos);
+ type_quals);
}
// clang_type will get the function prototype clang type after this call
@@ -6608,9 +6643,9 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
function_param_types.size(),
is_variadic,
type_quals);
-
+
bool ignore_containing_context = false;
-
+
if (type_name_cstr)
{
bool type_handled = false;
@@ -6619,12 +6654,10 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
ObjCLanguageRuntime::MethodName objc_method (type_name_cstr, true);
if (objc_method.IsValid(true))
{
- SymbolContext empty_sc;
ClangASTType class_opaque_type;
ConstString class_name(objc_method.GetClassName());
if (class_name)
{
- TypeList types;
TypeSP complete_objc_class_type_sp (FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, false));
if (complete_objc_class_type_sp)
@@ -6677,7 +6710,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
SymbolFileDWARF *class_symfile = NULL;
DWARFCompileUnitSP class_type_cu_sp;
const DWARFDebugInfoEntry *class_type_die = NULL;
-
+
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
if (debug_map_symfile)
{
@@ -6691,8 +6724,8 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
}
if (class_type_die)
{
- llvm::SmallVector<const DWARFDebugInfoEntry *, 0> failures;
-
+ DWARFDIECollection failures;
+
CopyUniqueClassMethodTypes (class_symfile,
class_type,
class_type_cu_sp.get(),
@@ -6700,12 +6733,12 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
dwarf_cu,
decl_ctx_die,
failures);
-
+
// FIXME do something with these failures that's smarter than
// just dropping them on the ground. Unfortunately classes don't
// like having stuff added to them after their definitions are
// complete...
-
+
type_ptr = m_die_to_type[die];
if (type_ptr && type_ptr != DIE_IS_BEING_PARSED)
{
@@ -6714,7 +6747,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
}
}
}
-
+
if (specification_die_offset != DW_INVALID_OFFSET)
{
// We have a specification which we are going to base our function
@@ -6773,7 +6806,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
// in the DWARF for C++ methods... Default to public for now...
if (accessibility == eAccessNone)
accessibility = eAccessPublic;
-
+
if (!is_static && !die->HasChildren())
{
// We have a C++ member function with no children (this pointer!)
@@ -6792,7 +6825,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
m_obj_file->GetFileSpec().GetPath().c_str());
const bool is_attr_used = false;
-
+
cxx_method_decl = class_opaque_type.AddMethodToCXXRecordType (type_name_cstr,
clang_type,
accessibility,
@@ -6802,7 +6835,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
is_explicit,
is_attr_used,
is_artificial);
-
+
type_handled = cxx_method_decl != NULL;
if (type_handled)
@@ -6811,17 +6844,17 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
Host::SetCrashDescription (NULL);
-
+
ClangASTMetadata metadata;
metadata.SetUserID(MakeUserID(die->GetOffset()));
-
+
if (!object_pointer_name.empty())
{
metadata.SetObjectPtrName(object_pointer_name.c_str());
if (log)
log->Printf ("Setting object pointer name: %s on method object %p.\n",
object_pointer_name.c_str(),
- cxx_method_decl);
+ static_cast<void*>(cxx_method_decl));
}
GetClangASTContext().SetMetadata (cxx_method_decl, metadata);
}
@@ -6841,7 +6874,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
// we need to modify the m_die_to_type so it doesn't think we are
// trying to parse this DIE anymore...
m_die_to_type[die] = NULL;
-
+
// Now we get the full type to force our class type to complete itself
// using the clang::ExternalASTSource protocol which will parse all
// base classes and all methods (including the method for this DIE).
@@ -6854,7 +6887,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
type_sp = type_ptr->shared_from_this();
break;
}
-
+
// FIXME This is fixing some even uglier behavior but we really need to
// uniq the methods of each class as well as the class itself.
// <rdar://problem/11240464>
@@ -6865,7 +6898,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
}
}
}
-
+
if (!type_handled)
{
// We just have a function that isn't part of a class
@@ -6893,17 +6926,17 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
ast.SetFunctionParameters (function_decl,
&function_param_decls.front(),
function_param_decls.size());
-
+
ClangASTMetadata metadata;
metadata.SetUserID(MakeUserID(die->GetOffset()));
-
+
if (!object_pointer_name.empty())
{
metadata.SetObjectPtrName(object_pointer_name.c_str());
if (log)
log->Printf ("Setting object pointer name: %s on function object %p.",
object_pointer_name.c_str(),
- function_decl);
+ static_cast<void*>(function_decl));
}
GetClangASTContext().SetMetadata (function_decl, metadata);
}
@@ -6940,7 +6973,6 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
for (i=0; i<num_attributes; ++i)
{
attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
{
switch (attr)
@@ -7022,13 +7054,12 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
dw_offset_t containing_type_die_offset = DW_INVALID_OFFSET;
const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
-
+
if (num_attributes > 0) {
uint32_t i;
for (i=0; i<num_attributes; ++i)
{
attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
{
switch (attr)
@@ -7040,10 +7071,10 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
}
}
}
-
+
Type *pointee_type = ResolveTypeUID(type_die_offset);
Type *class_type = ResolveTypeUID(containing_type_die_offset);
-
+
ClangASTType pointee_clang_type = pointee_type->GetClangForwardType();
ClangASTType class_clang_type = class_type->GetClangLayoutType();
@@ -7062,7 +7093,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
clang_type,
Type::eResolveStateForward));
}
-
+
break;
}
default:
@@ -7342,6 +7373,7 @@ SymbolFileDWARF::ParseVariableDIE
bool is_artificial = false;
bool location_is_const_value_data = false;
bool has_explicit_location = false;
+ DWARFFormValue const_value;
//AccessType accessibility = eAccessNone;
for (i=0; i<num_attributes; ++i)
@@ -7380,7 +7412,21 @@ SymbolFileDWARF::ParseVariableDIE
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
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);
+ if (data_length == 0)
+ {
+ const uint8_t *data_pointer = form_value.BlockData();
+ if (data_pointer)
+ {
+ data_length = form_value.Unsigned();
+ }
+ else if (DWARFFormValue::IsDataForm(form_value.Form()))
+ {
+ // we need to get the byte size of the type later after we create the variable
+ const_value = form_value;
+ }
+ }
+ else
+ location.CopyOpcodeData(module, debug_info_data, data_offset, data_length);
}
else
{
@@ -7455,7 +7501,7 @@ SymbolFileDWARF::ParseVariableDIE
// DWARF doesn't specify if a DW_TAG_variable is a local, global
// or static variable, so we have to do a little digging by
- // looking at the location of a varaible to see if it contains
+ // looking at the location of a variable to see if it contains
// a DW_OP_addr opcode _somewhere_ in the definition. I say
// somewhere because clang likes to combine small global variables
// into the same symbol and have locations like:
@@ -7592,10 +7638,15 @@ SymbolFileDWARF::ParseVariableDIE
if (symbol_context_scope)
{
+ SymbolFileTypeSP type_sp(new SymbolFileType(*this, type_uid));
+
+ if (const_value.Form() && type_sp && type_sp->GetType())
+ location.CopyOpcodeData(const_value.Unsigned(), type_sp->GetType()->GetByteSize(), dwarf_cu->GetAddressByteSize());
+
var_sp.reset (new Variable (MakeUserID(die->GetOffset()),
name,
mangled,
- SymbolFileTypeSP (new SymbolFileType(*this, type_uid)),
+ type_sp,
scope,
symbol_context_scope,
&decl,
@@ -7763,7 +7814,7 @@ SymbolFileDWARF::ParseVariables
if (block == NULL)
{
// This must be a specification or abstract origin with
- // a concrete block couterpart in the current function. We need
+ // a concrete block counterpart in the current function. We need
// to find the concrete block so we can correctly add the
// variable to it
DWARFCompileUnit *concrete_block_die_cu = dwarf_cu;
@@ -8011,12 +8062,11 @@ SymbolFileDWARF::LayoutRecordType (const clang::RecordDecl *record_decl,
if (log)
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::LayoutRecordType (record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u],base_offsets[%u], vbase_offsets[%u]) success = %i",
- record_decl,
- bit_size,
- alignment,
- (uint32_t)field_offsets.size(),
- (uint32_t)base_offsets.size(),
- (uint32_t)vbase_offsets.size(),
+ static_cast<const void*>(record_decl),
+ bit_size, alignment,
+ static_cast<uint32_t>(field_offsets.size()),
+ static_cast<uint32_t>(base_offsets.size()),
+ static_cast<uint32_t>(vbase_offsets.size()),
success);
return success;
}
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 8dac209361ed..178e5142d94b 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -368,9 +368,10 @@ protected:
lldb_private::TypeList* type_list,
std::vector<lldb_private::ClangASTType>& function_args,
std::vector<clang::ParmVarDecl*>& function_param_decls,
- unsigned &type_quals,
- lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
-
+ unsigned &type_quals);
+ // lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); // not currently needed
+
+
size_t ParseChildEnumerators(
const lldb_private::SymbolContext& sc,
lldb_private::ClangASTType &clang_type,
@@ -546,7 +547,7 @@ protected:
const DWARFDebugInfoEntry *src_class_die,
DWARFCompileUnit* dst_cu,
const DWARFDebugInfoEntry *dst_class_die,
- llvm::SmallVectorImpl <const DWARFDebugInfoEntry *> &failures);
+ DWARFDIECollection &failures);
bool
FixupAddress (lldb_private::Address &addr);
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index 856c42c2c9a6..af16c03a8c07 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -55,20 +55,19 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
Module *oso_module = exe_symfile->GetModuleByCompUnitInfo (this);
if (!oso_module)
return file_range_map;
-
+
ObjectFile *oso_objfile = oso_module->GetObjectFile();
if (!oso_objfile)
return file_range_map;
-
+
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP));
if (log)
{
ConstString object_name (oso_module->GetObjectName());
log->Printf("%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')",
- this,
+ static_cast<void*>(this),
oso_module->GetSpecificationDescription().c_str());
}
-
std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos;
if (exe_symfile->GetCompUnitInfosForModule(oso_module, cu_infos))
@@ -78,12 +77,12 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
Symtab *exe_symtab = exe_symfile->GetObjectFile()->GetSymtab();
ModuleSP oso_module_sp (oso_objfile->GetModule());
Symtab *oso_symtab = oso_objfile->GetSymtab();
-
+
///const uint32_t fun_resolve_flags = SymbolContext::Module | eSymbolContextCompUnit | eSymbolContextFunction;
//SectionList *oso_sections = oso_objfile->Sections();
// Now we need to make sections that map from zero based object
- // file addresses to where things eneded up in the main executable.
-
+ // file addresses to where things ended up in the main executable.
+
assert (comp_unit_info->first_symbol_index != UINT32_MAX);
// End index is one past the last valid symbol index
const uint32_t oso_end_idx = comp_unit_info->last_symbol_index + 1;
@@ -96,12 +95,12 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
{
if (exe_symbol->IsDebug() == false)
continue;
-
+
switch (exe_symbol->GetType())
{
default:
break;
-
+
case eSymbolTypeCode:
{
// For each N_FUN, or function that we run into in the debug map
@@ -112,7 +111,7 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
// before we parse any dwarf info so that when it goes get parsed
// all section/offset addresses that get registered will resolve
// correctly to the new addresses in the main executable.
-
+
// First we find the original symbol in the .o file's symbol table
Symbol *oso_fun_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
eSymbolTypeCode,
@@ -125,11 +124,11 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
exe_symbol->GetAddress().GetFileAddress(),
oso_fun_symbol->GetAddress().GetFileAddress(),
std::min<addr_t>(exe_symbol->GetByteSize(), oso_fun_symbol->GetByteSize()));
-
+
}
}
break;
-
+
case eSymbolTypeData:
{
// For each N_GSYM we remap the address for the global by making
@@ -144,13 +143,12 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
// fix up these addresses further after all globals have been
// parsed to span the gaps, or we can find the global variable
// sizes from the DWARF info as we are parsing.
-
+
// Next we find the non-stab entry that corresponds to the N_GSYM in the .o file
Symbol *oso_gsym_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
eSymbolTypeData,
Symtab::eDebugNo,
Symtab::eVisibilityAny);
-
if (exe_symbol && oso_gsym_symbol &&
exe_symbol->ValueIsAddress() &&
oso_gsym_symbol->ValueIsAddress())
@@ -166,7 +164,7 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
}
}
}
-
+
exe_symfile->FinalizeOSOFileRanges (this);
// We don't need the symbols anymore for the .o files
oso_objfile->ClearSymtab();
@@ -216,7 +214,7 @@ public:
SymbolVendor* symbol_vendor = Module::GetSymbolVendor(can_create, feedback_strm);
if (symbol_vendor)
{
- // Set a a pointer to this class to set our OSO DWARF file know
+ // Set a pointer to this class to set our OSO DWARF file know
// that the DWARF is being used along with a debug map and that
// it will have the remapped sections that we do below.
SymbolFileDWARF *oso_symfile = SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(symbol_vendor->GetSymbolFile());
@@ -308,7 +306,7 @@ void
SymbolFileDWARFDebugMap::InitializeObject()
{
// Install our external AST source callbacks so we can complete Clang types.
- llvm::OwningPtr<clang::ExternalASTSource> ast_source_ap (
+ llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap (
new ClangExternalASTSourceCallbacks (SymbolFileDWARFDebugMap::CompleteTagDecl,
SymbolFileDWARFDebugMap::CompleteObjCInterfaceDecl,
NULL,
@@ -341,6 +339,7 @@ SymbolFileDWARFDebugMap::InitOSO()
case ObjectFile::eTypeObjectFile:
case ObjectFile::eTypeStubLibrary:
case ObjectFile::eTypeUnknown:
+ case ObjectFile::eTypeJIT:
return;
case ObjectFile::eTypeExecutable:
@@ -505,10 +504,16 @@ SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo (CompileUnitInfo *comp_unit_inf
// use the debug map, to add new sections to each .o file and
// even though a .o file might not have changed, the sections
// that get added to the .o file can change.
+ ArchSpec oso_arch;
+ // Only adopt the architecture from the module (not the vendor or OS)
+ // since .o files for "i386-apple-ios" will historically show up as "i386-apple-macosx"
+ // due to the lack of a LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS
+ // load command...
+ oso_arch.SetTriple(m_obj_file->GetModule()->GetArchitecture().GetTriple().getArchName().str().c_str());
comp_unit_info->oso_sp->module_sp.reset (new DebugMapModule (obj_file->GetModule(),
GetCompUnitInfoIndex(comp_unit_info),
oso_file,
- m_obj_file->GetModule()->GetArchitecture(),
+ oso_arch,
oso_object ? &oso_object : NULL,
0,
oso_object ? &comp_unit_info->oso_mod_time : NULL));
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index 06330b98dc19..1493292d4b9b 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -393,7 +393,7 @@ protected:
LinkOSOFileAddress (SymbolFileDWARF *oso_symfile, lldb::addr_t oso_file_addr);
//------------------------------------------------------------------
- /// Given a line table full of lines with "file adresses" that are
+ /// Given a line table full of lines with "file addresses" that are
/// for a .o file represented by \a oso_symfile, link a new line table
/// and return it.
///
@@ -405,7 +405,7 @@ protected:
///
/// @return
/// Returns a valid line table full of linked addresses, or NULL
- /// if none of the line table adresses exist in the main
+ /// if none of the line table addresses exist in the main
/// executable.
//------------------------------------------------------------------
lldb_private::LineTable *
diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
index 9beba517ec83..8e85d4825281 100644
--- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -145,7 +145,7 @@ SymbolFileSymtab::GetNumCompileUnits()
if (m_source_indexes.empty())
return 0;
- // If we have any source file symbols we will logically orgnize the object symbols
+ // If we have any source file symbols we will logically organize the object symbols
// using these.
return m_source_indexes.size();
}
@@ -366,20 +366,6 @@ SymbolFileSymtab::FindFunctions(const RegularExpression& regex, bool include_inl
return 0;
}
-static int CountMethodArgs(const char *method_signature)
-{
- int num_args = 0;
-
- for (const char *colon_pos = strchr(method_signature, ':');
- colon_pos != NULL;
- colon_pos = strchr(colon_pos + 1, ':'))
- {
- num_args++;
- }
-
- return num_args;
-}
-
uint32_t
SymbolFileSymtab::FindTypes (const lldb_private::SymbolContext& sc,
const lldb_private::ConstString &name,
diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index 8ddc1cd2ee84..b8d56d3909e9 100644
--- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -42,7 +42,7 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange&
m_inst_emulator_ap.get())
{
- // The the instruction emulation subclass setup the unwind plan for the
+ // The instruction emulation subclass setup the unwind plan for the
// first instruction.
m_inst_emulator_ap->CreateFunctionEntryUnwind (unwind_plan);
@@ -83,7 +83,7 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange&
// Initialize the CFA with a known value. In the 32 bit case
// it will be 0x80000000, and in the 64 bit case 0x8000000000000000.
- // We use the address byte size to be safe for any future addresss sizes
+ // We use the address byte size to be safe for any future address sizes
m_initial_sp = (1ull << ((addr_byte_size * 8) - 1));
RegisterValue cfa_reg_value;
cfa_reg_value.SetUInt (m_initial_sp, m_cfa_reg_info.byte_size);
@@ -182,7 +182,7 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange&
// While parsing the instructions of this function, if we've ever
// seen the return address register (aka lr on arm) in a non-IsSame() state,
- // it has been saved on the stack. If it's evern back to IsSame(), we've
+ // it has been saved on the stack. If it's ever back to IsSame(), we've
// executed an epilogue.
if (ra_reg_num != LLDB_INVALID_REGNUM
&& m_curr_row->GetRegisterInfo (ra_reg_num, ra_regloc)
@@ -285,6 +285,14 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange&
}
bool
+UnwindAssemblyInstEmulation::AugmentUnwindPlanFromCallSite (AddressRange& func,
+ Thread& thread,
+ UnwindPlan& unwind_plan)
+{
+ return false;
+}
+
+bool
UnwindAssemblyInstEmulation::GetFastUnwindPlan (AddressRange& func,
Thread& thread,
UnwindPlan &unwind_plan)
@@ -358,7 +366,8 @@ UnwindAssemblyInstEmulation::GetPluginDescriptionStatic()
uint64_t
UnwindAssemblyInstEmulation::MakeRegisterKindValuePair (const RegisterInfo &reg_info)
{
- uint32_t reg_kind, reg_num;
+ lldb::RegisterKind reg_kind;
+ uint32_t reg_num;
if (EmulateInstruction::GetBestRegisterKindAndNumber (&reg_info, reg_kind, reg_num))
return (uint64_t)reg_kind << 24 | reg_num;
return 0ull;
diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
index 6a02f0a55104..758c3ce2e28b 100644
--- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
+++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
@@ -31,6 +31,11 @@ public:
lldb_private::UnwindPlan& unwind_plan);
virtual bool
+ AugmentUnwindPlanFromCallSite (lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan& unwind_plan);
+
+ virtual bool
GetFastUnwindPlan (lldb_private::AddressRange& func,
lldb_private::Thread& thread,
lldb_private::UnwindPlan &unwind_plan);
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index 1768798f71d4..32a21d2b8bb8 100644
--- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -27,12 +27,14 @@
using namespace lldb;
using namespace lldb_private;
-enum CPU {
+enum CPU
+{
k_i386,
k_x86_64
};
-enum i386_register_numbers {
+enum i386_register_numbers
+{
k_machine_eax = 0,
k_machine_ecx = 1,
k_machine_edx = 2,
@@ -44,7 +46,8 @@ enum i386_register_numbers {
k_machine_eip = 8
};
-enum x86_64_register_numbers {
+enum x86_64_register_numbers
+{
k_machine_rax = 0,
k_machine_rcx = 1,
k_machine_rdx = 2,
@@ -64,13 +67,15 @@ enum x86_64_register_numbers {
k_machine_rip = 16
};
-struct regmap_ent {
+struct regmap_ent
+{
const char *name;
int machine_regno;
int lldb_regno;
};
-static struct regmap_ent i386_register_map[] = {
+static struct regmap_ent i386_register_map[] =
+{
{"eax", k_machine_eax, -1},
{"ecx", k_machine_ecx, -1},
{"edx", k_machine_edx, -1},
@@ -82,11 +87,12 @@ static struct regmap_ent i386_register_map[] = {
{"eip", k_machine_eip, -1}
};
-const int size_of_i386_register_map = sizeof (i386_register_map) / sizeof (struct regmap_ent);
+const int size_of_i386_register_map = llvm::array_lengthof (i386_register_map);
static int i386_register_map_initialized = 0;
-static struct regmap_ent x86_64_register_map[] = {
+static struct regmap_ent x86_64_register_map[] =
+{
{"rax", k_machine_rax, -1},
{"rcx", k_machine_rcx, -1},
{"rdx", k_machine_rdx, -1},
@@ -106,7 +112,7 @@ static struct regmap_ent x86_64_register_map[] = {
{"rip", k_machine_rip, -1}
};
-const int size_of_x86_64_register_map = sizeof (x86_64_register_map) / sizeof (struct regmap_ent);
+const int size_of_x86_64_register_map = llvm::array_lengthof (x86_64_register_map);
static int x86_64_register_map_initialized = 0;
@@ -114,7 +120,8 @@ static int x86_64_register_map_initialized = 0;
// AssemblyParse_x86 local-file class definition & implementation functions
//-----------------------------------------------------------------------------------------------
-class AssemblyParse_x86 {
+class AssemblyParse_x86
+{
public:
AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu, ArchSpec &arch, AddressRange func);
@@ -123,6 +130,8 @@ public:
bool get_non_call_site_unwind_plan (UnwindPlan &unwind_plan);
+ bool augment_unwind_plan_from_call_site (AddressRange& func, UnwindPlan &unwind_plan);
+
bool get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_plan);
bool find_first_non_prologue_insn (Address &address);
@@ -135,9 +144,14 @@ private:
bool push_0_pattern_p ();
bool mov_rsp_rbp_pattern_p ();
bool sub_rsp_pattern_p (int& amount);
+ bool add_rsp_pattern_p (int& amount);
bool push_reg_p (int& regno);
+ bool pop_reg_p (int& regno);
+ bool push_imm_pattern_p ();
bool mov_reg_to_local_stack_frame_p (int& regno, int& fp_offset);
bool ret_pattern_p ();
+ bool pop_rbp_pattern_p ();
+ bool call_next_insn_pattern_p();
uint32_t extract_4 (uint8_t *b);
bool machine_regno_to_lldb_regno (int machine_regno, uint32_t& lldb_regno);
bool instruction_length (Address addr, int &length);
@@ -149,13 +163,13 @@ private:
Address m_cur_insn;
uint8_t m_cur_insn_bytes[kMaxInstructionByteSize];
- int m_machine_ip_regnum;
- int m_machine_sp_regnum;
- int m_machine_fp_regnum;
+ uint32_t m_machine_ip_regnum;
+ uint32_t m_machine_sp_regnum;
+ uint32_t m_machine_fp_regnum;
- int m_lldb_ip_regnum;
- int m_lldb_sp_regnum;
- int m_lldb_fp_regnum;
+ uint32_t m_lldb_ip_regnum;
+ uint32_t m_lldb_sp_regnum;
+ uint32_t m_lldb_fp_regnum;
int m_wordsize;
int m_cpu;
@@ -166,16 +180,16 @@ private:
};
AssemblyParse_x86::AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu, ArchSpec &arch, AddressRange func) :
- m_exe_ctx (exe_ctx),
- m_func_bounds(func),
+ m_exe_ctx (exe_ctx),
+ m_func_bounds(func),
m_cur_insn (),
m_machine_ip_regnum (LLDB_INVALID_REGNUM),
m_machine_sp_regnum (LLDB_INVALID_REGNUM),
m_machine_fp_regnum (LLDB_INVALID_REGNUM),
- m_lldb_ip_regnum (LLDB_INVALID_REGNUM),
+ m_lldb_ip_regnum (LLDB_INVALID_REGNUM),
m_lldb_sp_regnum (LLDB_INVALID_REGNUM),
m_lldb_fp_regnum (LLDB_INVALID_REGNUM),
- m_wordsize (-1),
+ m_wordsize (-1),
m_cpu(cpu),
m_arch(arch)
{
@@ -242,8 +256,8 @@ AssemblyParse_x86::AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu,
m_lldb_ip_regnum = lldb_regno;
}
- m_disasm_context = ::LLVMCreateDisasm(m_arch.GetTriple().getTriple().c_str(),
- (void*)this,
+ m_disasm_context = ::LLVMCreateDisasm(m_arch.GetTriple().getTriple().c_str(),
+ (void*)this,
/*TagType=*/1,
NULL,
NULL);
@@ -254,7 +268,7 @@ AssemblyParse_x86::~AssemblyParse_x86 ()
::LLVMDisasmDispose(m_disasm_context);
}
-// This function expects an x86 native register number (i.e. the bits stripped out of the
+// This function expects an x86 native register number (i.e. the bits stripped out of the
// actual instruction), not an lldb register number.
bool
@@ -262,7 +276,8 @@ AssemblyParse_x86::nonvolatile_reg_p (int machine_regno)
{
if (m_cpu == k_i386)
{
- switch (machine_regno) {
+ switch (machine_regno)
+ {
case k_machine_ebx:
case k_machine_ebp: // not actually a nonvolatile but often treated as such by convention
case k_machine_esi:
@@ -275,7 +290,8 @@ AssemblyParse_x86::nonvolatile_reg_p (int machine_regno)
}
if (m_cpu == k_x86_64)
{
- switch (machine_regno) {
+ switch (machine_regno)
+ {
case k_machine_rbx:
case k_machine_rsp:
case k_machine_rbp: // not actually a nonvolatile but often treated as such by convention
@@ -292,7 +308,7 @@ AssemblyParse_x86::nonvolatile_reg_p (int machine_regno)
}
-// Macro to detect if this is a REX mode prefix byte.
+// Macro to detect if this is a REX mode prefix byte.
#define REX_W_PREFIX_P(opcode) (((opcode) & (~0x5)) == 0x48)
// The high bit which should be added to the source register number (the "R" bit)
@@ -302,7 +318,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)
return true;
@@ -318,9 +335,20 @@ bool AssemblyParse_x86::push_0_pattern_p ()
return false;
}
+// pushq $0
+// pushl $0
+bool AssemblyParse_x86::push_imm_pattern_p ()
+{
+ uint8_t *p = m_cur_insn_bytes;
+ if (*p == 0x68 || *p == 0x6a)
+ return true;
+ return false;
+}
+
// 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)
p++;
@@ -331,57 +359,127 @@ bool AssemblyParse_x86::mov_rsp_rbp_pattern_p () {
return false;
}
-// subq $0x20, %rsp
-bool AssemblyParse_x86::sub_rsp_pattern_p (int& amount) {
+// subq $0x20, %rsp
+bool AssemblyParse_x86::sub_rsp_pattern_p (int& amount)
+{
uint8_t *p = m_cur_insn_bytes;
if (m_wordsize == 8 && *p == 0x48)
p++;
// 8-bit immediate operand
- if (*p == 0x83 && *(p + 1) == 0xec) {
+ if (*p == 0x83 && *(p + 1) == 0xec)
+ {
amount = (int8_t) *(p + 2);
return true;
}
// 32-bit immediate operand
- if (*p == 0x81 && *(p + 1) == 0xec) {
+ if (*p == 0x81 && *(p + 1) == 0xec)
+ {
+ amount = (int32_t) extract_4 (p + 2);
+ return true;
+ }
+ return false;
+}
+
+// addq $0x20, %rsp
+bool AssemblyParse_x86::add_rsp_pattern_p (int& amount)
+{
+ uint8_t *p = m_cur_insn_bytes;
+ if (m_wordsize == 8 && *p == 0x48)
+ p++;
+ // 8-bit immediate operand
+ if (*p == 0x83 && *(p + 1) == 0xc4)
+ {
+ amount = (int8_t) *(p + 2);
+ return true;
+ }
+ // 32-bit immediate operand
+ if (*p == 0x81 && *(p + 1) == 0xc4)
+ {
amount = (int32_t) extract_4 (p + 2);
return true;
}
- // Not handled: [0x83 0xc4] for imm8 with neg values
- // [0x81 0xc4] for imm32 with neg values
return false;
}
// pushq %rbx
-// pushl $ebx
-bool AssemblyParse_x86::push_reg_p (int& regno) {
+// pushl %ebx
+bool AssemblyParse_x86::push_reg_p (int& regno)
+{
uint8_t *p = m_cur_insn_bytes;
int regno_prefix_bit = 0;
// If we have a rex prefix byte, check to see if a B bit is set
- if (m_wordsize == 8 && *p == 0x41) {
+ if (m_wordsize == 8 && *p == 0x41)
+ {
regno_prefix_bit = 1 << 3;
p++;
}
- if (*p >= 0x50 && *p <= 0x57) {
+ if (*p >= 0x50 && *p <= 0x57)
+ {
regno = (*p - 0x50) | regno_prefix_bit;
return true;
}
return false;
}
+// popq %rbx
+// popl %ebx
+bool AssemblyParse_x86::pop_reg_p (int& regno)
+{
+ uint8_t *p = m_cur_insn_bytes;
+ int regno_prefix_bit = 0;
+ // If we have a rex prefix byte, check to see if a B bit is set
+ if (m_wordsize == 8 && *p == 0x41)
+ {
+ regno_prefix_bit = 1 << 3;
+ p++;
+ }
+ if (*p >= 0x58 && *p <= 0x5f)
+ {
+ regno = (*p - 0x58) | regno_prefix_bit;
+ return true;
+ }
+ return false;
+}
+
+// popq %rbp [0x5d]
+// popl %ebp [0x5d]
+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 ()
+{
+ uint8_t *p = m_cur_insn_bytes;
+ return (*p == 0xe8) && (*(p+1) == 0x0) && (*(p+2) == 0x0)
+ && (*(p+3) == 0x0) && (*(p+4) == 0x0);
+}
+
// Look for an instruction sequence storing a nonvolatile register
// on to the stack frame.
// movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0]
// movl %eax, -0xc(%ebp) [0x89 0x45 0xf4]
-bool AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int& regno, int& rbp_offset) {
+
+// The offset value returned in rbp_offset will be positive --
+// but it must be subtraced from the frame base register to get
+// 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)
+{
uint8_t *p = m_cur_insn_bytes;
int src_reg_prefix_bit = 0;
int target_reg_prefix_bit = 0;
- if (m_wordsize == 8 && REX_W_PREFIX_P (*p)) {
+ if (m_wordsize == 8 && REX_W_PREFIX_P (*p))
+ {
src_reg_prefix_bit = REX_W_SRCREG (*p) << 3;
target_reg_prefix_bit = REX_W_DSTREG (*p) << 3;
- if (target_reg_prefix_bit == 1) {
+ if (target_reg_prefix_bit == 1)
+ {
// rbp/ebp don't need a prefix bit - we know this isn't the
// reg we care about.
return false;
@@ -389,12 +487,13 @@ bool AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int& regno, int& rbp_off
p++;
}
- if (*p == 0x89) {
+ if (*p == 0x89)
+ {
/* Mask off the 3-5 bits which indicate the destination register
if this is a ModR/M byte. */
int opcode_destreg_masked_out = *(p + 1) & (~0x38);
- /* Is this a ModR/M byte with Mod bits 01 and R/M bits 101
+ /* Is this a ModR/M byte with Mod bits 01 and R/M bits 101
and three bits between them, e.g. 01nnn101
We're looking for a destination of ebp-disp8 or ebp-disp32. */
int immsize;
@@ -421,8 +520,8 @@ bool AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int& regno, int& rbp_off
}
// ret [0xc9] or [0xc2 imm8] or [0xca imm8]
-bool
-AssemblyParse_x86::ret_pattern_p ()
+bool
+AssemblyParse_x86::ret_pattern_p ()
{
uint8_t *p = m_cur_insn_bytes;
if (*p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3)
@@ -439,7 +538,7 @@ AssemblyParse_x86::extract_4 (uint8_t *b)
return v;
}
-bool
+bool
AssemblyParse_x86::machine_regno_to_lldb_regno (int machine_regno, uint32_t &lldb_regno)
{
struct regmap_ent *ent;
@@ -479,11 +578,12 @@ AssemblyParse_x86::instruction_length (Address addr, int &length)
const bool prefer_file_cache = true;
Error error;
Target *target = m_exe_ctx.GetTargetPtr();
- if (target->ReadMemory (addr, prefer_file_cache, opcode_data.data(), max_op_byte_size, error) == -1)
+ if (target->ReadMemory (addr, prefer_file_cache, opcode_data.data(),
+ max_op_byte_size, error) == static_cast<size_t>(-1))
{
return false;
}
-
+
char out_string[512];
const addr_t pc = addr.GetFileAddress();
const size_t inst_size = ::LLVMDisasmInstruction (m_disasm_context,
@@ -498,7 +598,7 @@ AssemblyParse_x86::instruction_length (Address addr, int &length)
}
-bool
+bool
AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
{
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -552,7 +652,8 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
// An unrecognized/junk instruction
break;
}
- if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes, insn_len, error) == -1)
+ if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes,
+ insn_len, error) == static_cast<size_t>(-1))
{
// Error reading the instruction out of the file, stop scanning
break;
@@ -631,7 +732,13 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
{
row->SetOffset (current_func_text_offset + insn_len);
UnwindPlan::Row::RegisterLocation regloc;
- regloc.SetAtCFAPlusOffset (-row->GetCFAOffset());
+
+ // 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()));
+
row->SetRegisterInfo (lldb_regno, regloc);
unwind_plan.AppendRow (row);
// Allocate a new Row, populate it with the existing Row contents.
@@ -679,45 +786,65 @@ loopnext:
m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len);
current_func_text_offset += insn_len;
}
-
+
// 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
- // [ 0x5d ] mov %rbp, %rsp
+ // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp)
+ // [ 0xc3 ] ret
+
+ // or
+
+ // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp)
+ // [ 0xe9 xx xx xx xx ] jmp objc_retainAutoreleaseReturnValue (this is sometimes the final insn in the function)
+
+ // or
+
+ // [ 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)
// 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)
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());
-
+
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) != -1)
+ if (target->ReadMemory (last_seven_bytes, prefer_file_cache, bytebuf, 7,
+ error) != static_cast<size_t>(-1))
{
- if (bytebuf[5] == 0x5d && bytebuf[6] == 0xc3) // mov, ret
+ if (bytebuf[5] == 0x5d && bytebuf[6] == 0xc3) // mov & ret
{
ret_insn_offset = m_func_bounds.GetByteSize() - 1;
}
- else if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3 && bytebuf[2] == 0xe8) // mov, ret, call
+ 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
{
ret_insn_offset = m_func_bounds.GetByteSize() - 6;
}
}
- } else if (m_func_bounds.GetByteSize() > 2)
+ }
+ 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) != -1)
+ if (target->ReadMemory (last_two_bytes, prefer_file_cache, bytebuf, 2,
+ error) != static_cast<size_t>(-1))
{
- if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3) // mov, ret
+ if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3) // mov & ret
{
ret_insn_offset = m_func_bounds.GetByteSize() - 1;
}
@@ -734,7 +861,7 @@ loopnext:
epi_row->SetOffset (ret_insn_offset);
epi_row->SetCFARegister (m_lldb_sp_regnum);
epi_row->SetCFAOffset (m_wordsize);
-
+
// 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);
@@ -745,7 +872,7 @@ loopnext:
unwind_plan.AppendRow (epi_row);
}
-
+
unwind_plan.SetSourceName ("assembly insn profiling");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
@@ -753,13 +880,211 @@ loopnext:
return true;
}
-/* The "fast unwind plan" is valid for functions that follow the usual convention of
+bool
+AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, UnwindPlan &unwind_plan)
+{
+ // Is func address valid?
+ Address addr_start = func.GetBaseAddress();
+ if (!addr_start.IsValid())
+ return false;
+
+ // Is original unwind_plan valid?
+ // unwind_plan should have at least one row which is ABI-default (CFA register is sp),
+ // and another row in mid-function.
+ if (unwind_plan.GetRowCount() < 2)
+ return false;
+ UnwindPlan::RowSP first_row = unwind_plan.GetRowAtIndex (0);
+ if (first_row->GetOffset() != 0)
+ return false;
+ uint32_t cfa_reg = m_exe_ctx.GetThreadPtr()->GetRegisterContext()
+ ->ConvertRegisterKindToRegisterNumber (unwind_plan.GetRegisterKind(),
+ first_row->GetCFARegister());
+ if (cfa_reg != m_lldb_sp_regnum || first_row->GetCFAOffset() != m_wordsize)
+ return false;
+
+ 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));
+ while (func.ContainsFileAddress (m_cur_insn))
+ {
+ int insn_len;
+ if (!instruction_length (m_cur_insn, insn_len)
+ || insn_len == 0 || insn_len > kMaxInstructionByteSize)
+ {
+ // An unrecognized/junk instruction.
+ break;
+ }
+ const bool prefer_file_cache = true;
+ Error error;
+ if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes,
+ insn_len, error) == static_cast<size_t>(-1))
+ {
+ // Error reading the instruction out of the file, stop scanning.
+ break;
+ }
+
+ // Advance offsets.
+ offset += insn_len;
+ m_cur_insn.SetOffset(m_cur_insn.GetOffset() + insn_len);
+
+ // 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)
+ {
+ *row = *original_row;
+ continue;
+ }
+
+ if (row_id == 0)
+ {
+ // If we are here, compiler didn't generate CFI for prologue.
+ // This won't happen to GCC or clang.
+ // In this case, bail out directly.
+ return false;
+ }
+
+ // Inspect the instruction to check if we need a new row for it.
+ cfa_reg = m_exe_ctx.GetThreadPtr()->GetRegisterContext()
+ ->ConvertRegisterKindToRegisterNumber (unwind_plan.GetRegisterKind(),
+ row->GetCFARegister());
+ if (cfa_reg == m_lldb_sp_regnum)
+ {
+ // CFA register is sp.
+
+ // call next instruction
+ // call 0
+ // => pop %ebx
+ if (call_next_insn_pattern_p ())
+ {
+ row->SetOffset (offset);
+ row->SetCFAOffset (m_wordsize + row->GetCFAOffset());
+
+ UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
+ unwind_plan.InsertRow (new_row);
+ unwind_plan_updated = true;
+ continue;
+ }
+
+ // push/pop register
+ int regno;
+ if (push_reg_p (regno))
+ {
+ row->SetOffset (offset);
+ row->SetCFAOffset (m_wordsize + row->GetCFAOffset());
+
+ UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
+ unwind_plan.InsertRow (new_row);
+ unwind_plan_updated = true;
+ continue;
+ }
+ if (pop_reg_p (regno))
+ {
+ // Technically, this might be a nonvolatile register recover in epilogue.
+ // We should reset RegisterInfo for the register.
+ // But in practice, previous rule for the register is still valid...
+ // So we ignore this case.
+
+ row->SetOffset (offset);
+ row->SetCFAOffset (-m_wordsize + row->GetCFAOffset());
+
+ UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
+ unwind_plan.InsertRow (new_row);
+ unwind_plan_updated = true;
+ continue;
+ }
+
+ // push imm
+ if (push_imm_pattern_p ())
+ {
+ row->SetOffset (offset);
+ row->SetCFAOffset (m_wordsize + row->GetCFAOffset());
+ UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
+ unwind_plan.InsertRow (new_row);
+ unwind_plan_updated = true;
+ continue;
+ }
+
+ // add/sub %rsp/%esp
+ int amount;
+ if (add_rsp_pattern_p (amount))
+ {
+ row->SetOffset (offset);
+ row->SetCFAOffset (-amount + row->GetCFAOffset());
+
+ UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
+ unwind_plan.InsertRow (new_row);
+ unwind_plan_updated = true;
+ continue;
+ }
+ if (sub_rsp_pattern_p (amount))
+ {
+ row->SetOffset (offset);
+ row->SetCFAOffset (amount + row->GetCFAOffset());
+
+ UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
+ unwind_plan.InsertRow (new_row);
+ unwind_plan_updated = true;
+ continue;
+ }
+ }
+ else if (cfa_reg == m_lldb_fp_regnum)
+ {
+ // CFA register is fp.
+
+ // The only case we care about is epilogue:
+ // [0x5d] pop %rbp/%ebp
+ // => [0xc3] ret
+ if (pop_rbp_pattern_p ())
+ {
+ if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes,
+ 1, error) != static_cast<size_t>(-1)
+ && ret_pattern_p ())
+ {
+ row->SetOffset (offset);
+ row->SetCFARegister (first_row->GetCFARegister());
+ row->SetCFAOffset (m_wordsize);
+
+ UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
+ unwind_plan.InsertRow (new_row);
+ unwind_plan_updated = true;
+ continue;
+ }
+ }
+ }
+ else
+ {
+ // CFA register is not sp or fp.
+
+ // This must be hand-written assembly.
+ // Just trust eh_frame and assume we have finished.
+ break;
+ }
+ }
+
+ unwind_plan.SetPlanValidAddressRange (func);
+ if (unwind_plan_updated)
+ {
+ std::string unwind_plan_source (unwind_plan.GetSourceName().AsCString());
+ unwind_plan_source += " plus augmentation from assembly parsing";
+ unwind_plan.SetSourceName (unwind_plan_source.c_str());
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ }
+ return true;
+}
+
+/* The "fast unwind plan" is valid for functions that follow the usual convention of
using the frame pointer register (ebp, rbp), i.e. the function prologue looks like
push %rbp [0x55]
mov %rsp,%rbp [0x48 0x89 0xe5] (this is a 2-byte insn seq on i386)
*/
-bool
+bool
AssemblyParse_x86::get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_plan)
{
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -776,7 +1101,8 @@ AssemblyParse_x86::get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_
uint8_t bytebuf[4];
Error error;
const bool prefer_file_cache = true;
- if (target->ReadMemory (func.GetBaseAddress(), prefer_file_cache, bytebuf, sizeof (bytebuf), error) == -1)
+ if (target->ReadMemory (func.GetBaseAddress(), prefer_file_cache, bytebuf,
+ sizeof (bytebuf), error) == static_cast<size_t>(-1))
return false;
uint8_t i386_prologue[] = {0x55, 0x89, 0xe5};
@@ -821,7 +1147,7 @@ AssemblyParse_x86::get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_
newrow = new UnwindPlan::Row;
*newrow = *row.get();
row.reset(newrow);
-
+
// mov %rsp, %rbp has executed
row->SetCFARegister (m_lldb_fp_regnum);
row->SetCFAOffset (2 * m_wordsize);
@@ -839,7 +1165,7 @@ AssemblyParse_x86::get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_
return true;
}
-bool
+bool
AssemblyParse_x86::find_first_non_prologue_insn (Address &address)
{
m_cur_insn = m_func_bounds.GetBaseAddress ();
@@ -859,7 +1185,8 @@ AssemblyParse_x86::find_first_non_prologue_insn (Address &address)
// An error parsing the instruction, i.e. probably data/garbage - stop scanning
break;
}
- if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes, insn_len, error) == -1)
+ if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes,
+ insn_len, error) == static_cast<size_t>(-1))
{
// Error reading the instruction out of the file, stop scanning
break;
@@ -886,11 +1213,11 @@ AssemblyParse_x86::find_first_non_prologue_insn (Address &address)
//-----------------------------------------------------------------------------------------------
-// UnwindAssemblyParser_x86 method definitions
+// UnwindAssemblyParser_x86 method definitions
//-----------------------------------------------------------------------------------------------
-UnwindAssembly_x86::UnwindAssembly_x86 (const ArchSpec &arch, int cpu) :
- lldb_private::UnwindAssembly(arch),
+UnwindAssembly_x86::UnwindAssembly_x86 (const ArchSpec &arch, int cpu) :
+ lldb_private::UnwindAssembly(arch),
m_cpu(cpu),
m_arch(arch)
{
@@ -910,6 +1237,14 @@ 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
UnwindAssembly_x86::GetFastUnwindPlan (AddressRange& func, Thread& thread, UnwindPlan &unwind_plan)
{
ExecutionContext exe_ctx (thread.shared_from_this());
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
index eebaa7b6c803..8a4fe7c09800 100644
--- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
+++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
@@ -27,6 +27,11 @@ public:
lldb_private::UnwindPlan& unwind_plan);
virtual bool
+ AugmentUnwindPlanFromCallSite (lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan& unwind_plan);
+
+ virtual bool
GetFastUnwindPlan (lldb_private::AddressRange& func,
lldb_private::Thread& thread,
lldb_private::UnwindPlan &unwind_plan);
diff --git a/source/Symbol/Block.cpp b/source/Symbol/Block.cpp
index 4ab86e54bf68..6a5c651cd017 100644
--- a/source/Symbol/Block.cpp
+++ b/source/Symbol/Block.cpp
@@ -24,7 +24,7 @@ using namespace lldb_private;
Block::Block(lldb::user_id_t uid) :
UserID(uid),
- m_parent_scope (NULL),
+ m_parent_scope (nullptr),
m_children (),
m_ranges (),
m_inlineInfoSP (),
@@ -62,7 +62,7 @@ Block::GetDescription(Stream *s, Function *function, lldb::DescriptionLevel leve
}
}
- if (m_inlineInfoSP.get() != NULL)
+ if (m_inlineInfoSP.get() != nullptr)
{
bool show_fullpaths = (level == eDescriptionLevelVerbose);
m_inlineInfoSP->Dump(s, show_fullpaths);
@@ -83,15 +83,15 @@ Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
}
}
- s->Printf("%p: ", this);
+ s->Printf("%p: ", static_cast<const void*>(this));
s->Indent();
- *s << "Block" << ((const UserID&)*this);
+ *s << "Block" << static_cast<const UserID&>(*this);
const Block* parent_block = GetParent();
if (parent_block)
{
s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID());
}
- if (m_inlineInfoSP.get() != NULL)
+ if (m_inlineInfoSP.get() != nullptr)
{
bool show_fullpaths = false;
m_inlineInfoSP->Dump(s, show_fullpaths);
@@ -100,12 +100,12 @@ Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
if (!m_ranges.IsEmpty())
{
*s << ", ranges =";
-
+
size_t num_ranges = m_ranges.GetSize();
for (size_t i=0; i<num_ranges; ++i)
{
const Range &range = m_ranges.GetEntryRef(i);
- if (parent_block != NULL && parent_block->Contains(range) == false)
+ if (parent_block != nullptr && parent_block->Contains(range) == false)
*s << '!';
else
*s << ' ';
@@ -139,7 +139,7 @@ Block::FindBlockByID (user_id_t block_id)
if (block_id == GetID())
return this;
- Block *matching_block = NULL;
+ Block *matching_block = nullptr;
collection::const_iterator pos, end = m_children.end();
for (pos = m_children.begin(); pos != end; ++pos)
{
@@ -171,7 +171,7 @@ Block::CalculateSymbolContextCompileUnit ()
{
if (m_parent_scope)
return m_parent_scope->CalculateSymbolContextCompileUnit ();
- return NULL;
+ return nullptr;
}
Function *
@@ -179,7 +179,7 @@ Block::CalculateSymbolContextFunction ()
{
if (m_parent_scope)
return m_parent_scope->CalculateSymbolContextFunction ();
- return NULL;
+ return nullptr;
}
Block *
@@ -214,7 +214,7 @@ Block::DumpAddressRanges (Stream *s, lldb::addr_t base_addr)
bool
Block::Contains (addr_t range_offset) const
{
- return m_ranges.FindEntryThatContains(range_offset) != NULL;
+ return m_ranges.FindEntryThatContains(range_offset) != nullptr;
}
bool
@@ -226,7 +226,7 @@ Block::Contains (const Block *block) const
// Walk the parent chain for "block" and see if any if them match this block
const Block *block_parent;
for (block_parent = block->GetParent();
- block_parent != NULL;
+ block_parent != nullptr;
block_parent = block_parent->GetParent())
{
if (this == block_parent)
@@ -238,7 +238,7 @@ Block::Contains (const Block *block) const
bool
Block::Contains (const Range& range) const
{
- return m_ranges.FindEntryThatContains (range) != NULL;
+ return m_ranges.FindEntryThatContains (range) != nullptr;
}
Block *
@@ -246,7 +246,7 @@ Block::GetParent () const
{
if (m_parent_scope)
return m_parent_scope->CalculateSymbolContextBlock();
- return NULL;
+ return nullptr;
}
Block *
@@ -268,7 +268,7 @@ Block::GetInlinedParent ()
else
return parent_block->GetInlinedParent();
}
- return NULL;
+ return nullptr;
}
@@ -472,7 +472,7 @@ Block::GetBlockVariableList (bool can_create)
{
if (m_parsed_block_variables == false)
{
- if (m_variable_list_sp.get() == NULL && can_create)
+ if (m_variable_list_sp.get() == nullptr && can_create)
{
m_parsed_block_variables = true;
SymbolContext sc;
@@ -505,7 +505,7 @@ Block::AppendBlockVariables (bool can_create,
{
Block *child_block = pos->get();
if (stop_if_child_block_is_inlined_function == false ||
- child_block->GetInlinedFunctionInfo() == NULL)
+ child_block->GetInlinedFunctionInfo() == nullptr)
{
num_variables_added += child_block->AppendBlockVariables (can_create,
get_child_block_variables,
@@ -529,7 +529,7 @@ Block::AppendVariables
uint32_t num_variables_added = 0;
VariableListSP variable_list_sp(GetBlockVariableList(can_create));
- bool is_inlined_function = GetInlinedFunctionInfo() != NULL;
+ bool is_inlined_function = GetInlinedFunctionInfo() != nullptr;
if (variable_list_sp.get())
{
num_variables_added = variable_list_sp->GetSize();
@@ -556,17 +556,17 @@ Block::GetClangDeclContext()
CalculateSymbolContext (&sc);
if (!sc.module_sp)
- return NULL;
+ return nullptr;
SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
if (!sym_vendor)
- return NULL;
+ return nullptr;
SymbolFile *sym_file = sym_vendor->GetSymbolFile();
if (!sym_file)
- return NULL;
+ return nullptr;
return sym_file->GetClangDeclContextForTypeUID (sc, m_uid);
}
@@ -606,7 +606,7 @@ Block::GetSibling() const
if (parent_block)
return parent_block->GetSiblingForChild (this);
}
- return NULL;
+ return nullptr;
}
// A parent of child blocks can be asked to find a sibling block given
// one of its child blocks
@@ -626,6 +626,6 @@ Block::GetSiblingForChild (const Block *child_block) const
}
}
}
- return NULL;
+ return nullptr;
}
diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp
index 4f30ccfc0de5..aae96bfa9a3b 100644
--- a/source/Symbol/ClangASTContext.cpp
+++ b/source/Symbol/ClangASTContext.cpp
@@ -16,7 +16,7 @@
// Other libraries and framework includes
// Clang headers like to use NDEBUG inside of them to enable/disable debug
-// releated features using "#ifndef NDEBUG" preprocessor blocks to do one thing
+// related features using "#ifndef NDEBUG" preprocessor blocks to do one thing
// or another. This is bad because it means that if clang was built in release
// mode, it assumes that you are building in release mode which is not always
// the case. You can end up with functions that are defined as empty in header
@@ -79,6 +79,16 @@ using namespace lldb_private;
using namespace llvm;
using namespace clang;
+typedef llvm::DenseMap<clang::ASTContext *, ClangASTContext*> ClangASTMap;
+
+static ClangASTMap &
+GetASTMap()
+{
+ static ClangASTMap g_map;
+ return g_map;
+}
+
+
clang::AccessSpecifier
ClangASTContext::ConvertAccessTypeToAccessSpecifier (AccessType access)
{
@@ -103,7 +113,7 @@ ParseLangArgs
{
// FIXME: Cleanup per-file based stuff.
- // Set some properties which depend soley on the input kind; it would be nice
+ // Set some properties which depend solely on the input kind; it would be nice
// to move these to the language standard, and have the driver resolve the
// input kind + language standard.
if (IK == IK_Asm) {
@@ -276,9 +286,9 @@ ClangASTContext::ClangASTContext (const char *target_triple) :
m_identifier_table_ap(),
m_selector_table_ap(),
m_builtins_ap(),
- m_callback_tag_decl (NULL),
- m_callback_objc_decl (NULL),
- m_callback_baton (NULL),
+ m_callback_tag_decl (nullptr),
+ m_callback_objc_decl (nullptr),
+ m_callback_baton (nullptr),
m_pointer_byte_size (0)
{
@@ -291,6 +301,11 @@ ClangASTContext::ClangASTContext (const char *target_triple) :
//----------------------------------------------------------------------
ClangASTContext::~ClangASTContext()
{
+ if (m_ast_ap.get())
+ {
+ GetASTMap().erase(m_ast_ap.get());
+ }
+
m_builtins_ap.reset();
m_selector_table_ap.reset();
m_identifier_table_ap.reset();
@@ -342,12 +357,12 @@ ClangASTContext::HasExternalSource ()
{
ASTContext *ast = getASTContext();
if (ast)
- return ast->getExternalSource () != NULL;
+ return ast->getExternalSource () != nullptr;
return false;
}
void
-ClangASTContext::SetExternalSource (llvm::OwningPtr<ExternalASTSource> &ast_source_ap)
+ClangASTContext::SetExternalSource (llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_ap)
{
ASTContext *ast = getASTContext();
if (ast)
@@ -365,7 +380,7 @@ ClangASTContext::RemoveExternalSource ()
if (ast)
{
- llvm::OwningPtr<ExternalASTSource> empty_ast_source_ap;
+ llvm::IntrusiveRefCntPtr<ExternalASTSource> empty_ast_source_ap;
ast->setExternalSource (empty_ast_source_ap);
ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(false);
//ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(false);
@@ -377,15 +392,14 @@ ClangASTContext::RemoveExternalSource ()
ASTContext *
ClangASTContext::getASTContext()
{
- if (m_ast_ap.get() == NULL)
+ if (m_ast_ap.get() == nullptr)
{
m_ast_ap.reset(new ASTContext (*getLanguageOptions(),
*getSourceManager(),
- getTargetInfo(),
*getIdentifierTable(),
*getSelectorTable(),
- *getBuiltinContext(),
- 0));
+ *getBuiltinContext()));
+ m_ast_ap->InitBuiltinTypes(*getTargetInfo());
if ((m_callback_tag_decl || m_callback_objc_decl) && m_callback_baton)
{
@@ -394,14 +408,23 @@ ClangASTContext::getASTContext()
}
m_ast_ap->getDiagnostics().setClient(getDiagnosticConsumer(), false);
+
+ GetASTMap().insert(std::make_pair(m_ast_ap.get(), this));
}
return m_ast_ap.get();
}
+ClangASTContext*
+ClangASTContext::GetASTContext (clang::ASTContext* ast)
+{
+ ClangASTContext *clang_ast = GetASTMap().lookup(ast);
+ return clang_ast;
+}
+
Builtin::Context *
ClangASTContext::getBuiltinContext()
{
- if (m_builtins_ap.get() == NULL)
+ if (m_builtins_ap.get() == nullptr)
m_builtins_ap.reset (new Builtin::Context());
return m_builtins_ap.get();
}
@@ -409,15 +432,15 @@ ClangASTContext::getBuiltinContext()
IdentifierTable *
ClangASTContext::getIdentifierTable()
{
- if (m_identifier_table_ap.get() == NULL)
- m_identifier_table_ap.reset(new IdentifierTable (*ClangASTContext::getLanguageOptions(), NULL));
+ if (m_identifier_table_ap.get() == nullptr)
+ m_identifier_table_ap.reset(new IdentifierTable (*ClangASTContext::getLanguageOptions(), nullptr));
return m_identifier_table_ap.get();
}
LangOptions *
ClangASTContext::getLanguageOptions()
{
- if (m_language_options_ap.get() == NULL)
+ if (m_language_options_ap.get() == nullptr)
{
m_language_options_ap.reset(new LangOptions());
ParseLangArgs(*m_language_options_ap, IK_ObjCXX);
@@ -429,7 +452,7 @@ ClangASTContext::getLanguageOptions()
SelectorTable *
ClangASTContext::getSelectorTable()
{
- if (m_selector_table_ap.get() == NULL)
+ if (m_selector_table_ap.get() == nullptr)
m_selector_table_ap.reset (new SelectorTable());
return m_selector_table_ap.get();
}
@@ -437,7 +460,7 @@ ClangASTContext::getSelectorTable()
clang::FileManager *
ClangASTContext::getFileManager()
{
- if (m_file_manager_ap.get() == NULL)
+ if (m_file_manager_ap.get() == nullptr)
{
clang::FileSystemOptions file_system_options;
m_file_manager_ap.reset(new clang::FileManager(file_system_options));
@@ -448,7 +471,7 @@ ClangASTContext::getFileManager()
clang::SourceManager *
ClangASTContext::getSourceManager()
{
- if (m_source_manager_ap.get() == NULL)
+ if (m_source_manager_ap.get() == nullptr)
m_source_manager_ap.reset(new clang::SourceManager(*getDiagnosticsEngine(), *getFileManager()));
return m_source_manager_ap.get();
}
@@ -456,7 +479,7 @@ ClangASTContext::getSourceManager()
clang::DiagnosticsEngine *
ClangASTContext::getDiagnosticsEngine()
{
- if (m_diagnostics_engine_ap.get() == NULL)
+ if (m_diagnostics_engine_ap.get() == nullptr)
{
llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs());
m_diagnostics_engine_ap.reset(new DiagnosticsEngine(diag_id_sp, new DiagnosticOptions()));
@@ -494,23 +517,21 @@ private:
DiagnosticConsumer *
ClangASTContext::getDiagnosticConsumer()
{
- if (m_diagnostic_consumer_ap.get() == NULL)
+ if (m_diagnostic_consumer_ap.get() == nullptr)
m_diagnostic_consumer_ap.reset(new NullDiagnosticConsumer);
return m_diagnostic_consumer_ap.get();
}
-TargetOptions *
-ClangASTContext::getTargetOptions()
-{
- if (m_target_options_rp.getPtr() == NULL && !m_target_triple.empty())
+std::shared_ptr<TargetOptions> &
+ClangASTContext::getTargetOptions() {
+ if (m_target_options_rp.get() == nullptr && !m_target_triple.empty())
{
- m_target_options_rp.reset ();
- m_target_options_rp = new TargetOptions();
- if (m_target_options_rp.getPtr() != NULL)
+ m_target_options_rp = std::make_shared<TargetOptions>();
+ if (m_target_options_rp.get() != nullptr)
m_target_options_rp->Triple = m_target_triple;
}
- return m_target_options_rp.getPtr();
+ return m_target_options_rp;
}
@@ -518,7 +539,7 @@ TargetInfo *
ClangASTContext::getTargetInfo()
{
// target_triple should be something like "x86_64-apple-macosx"
- if (m_target_info_ap.get() == NULL && !m_target_triple.empty())
+ if (m_target_info_ap.get() == nullptr && !m_target_triple.empty())
m_target_info_ap.reset (TargetInfo::CreateTargetInfo(*getDiagnosticsEngine(), getTargetOptions()));
return m_target_info_ap.get();
}
@@ -650,7 +671,7 @@ ClangASTContext::GetBasicTypeEnumeration (const ConstString &name)
g_type_map.Append(ConstString("__int128_t").GetCString(), eBasicTypeInt128);
g_type_map.Append(ConstString("__uint128_t").GetCString(), eBasicTypeUnsignedInt128);
- // Miscelaneous
+ // Miscellaneous
g_type_map.Append(ConstString("bool").GetCString(), eBasicTypeBool);
g_type_map.Append(ConstString("float").GetCString(), eBasicTypeFloat);
g_type_map.Append(ConstString("double").GetCString(), eBasicTypeDouble);
@@ -696,7 +717,7 @@ ClangASTContext::GetBasicType (ASTContext *ast, lldb::BasicType basic_type)
{
if (ast)
{
- clang_type_t clang_type = NULL;
+ clang_type_t clang_type = nullptr;
switch (basic_type)
{
@@ -811,7 +832,7 @@ ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name
ASTContext *ast = getASTContext();
#define streq(a,b) strcmp(a,b) == 0
- assert (ast != NULL);
+ assert (ast != nullptr);
if (ast)
{
switch (dw_ate)
@@ -1134,9 +1155,9 @@ ClangASTContext::CreateRecordType (DeclContext *decl_ctx,
ClangASTMetadata *metadata)
{
ASTContext *ast = getASTContext();
- assert (ast != NULL);
+ assert (ast != nullptr);
- if (decl_ctx == NULL)
+ if (decl_ctx == nullptr)
decl_ctx = ast->getTranslationUnitDecl();
@@ -1160,7 +1181,7 @@ ClangASTContext::CreateRecordType (DeclContext *decl_ctx,
decl_ctx,
SourceLocation(),
SourceLocation(),
- is_anonymous ? NULL : &ast->Idents.get(name));
+ is_anonymous ? nullptr : &ast->Idents.get(name));
if (is_anonymous)
decl->setAnonymousStructOrUnion(true);
@@ -1194,7 +1215,7 @@ CreateTemplateParameterList (ASTContext *ast,
{
const char *name = template_param_infos.names[i];
- IdentifierInfo *identifier_info = NULL;
+ IdentifierInfo *identifier_info = nullptr;
if (name && name[0])
identifier_info = &ast->Idents.get(name);
if (template_param_infos.args[i].getKind() == TemplateArgument::Integral)
@@ -1208,7 +1229,7 @@ CreateTemplateParameterList (ASTContext *ast,
identifier_info,
template_param_infos.args[i].getIntegralType(),
parameter_pack,
- NULL));
+ nullptr));
}
else
@@ -1277,7 +1298,7 @@ ClangASTContext::CreateFunctionTemplateSpecializationInfo (FunctionDecl *func_de
func_decl->setFunctionTemplateSpecialization (func_tmpl_decl,
&template_args,
- NULL);
+ nullptr);
}
@@ -1290,8 +1311,8 @@ ClangASTContext::CreateClassTemplateDecl (DeclContext *decl_ctx,
{
ASTContext *ast = getASTContext();
- ClassTemplateDecl *class_template_decl = NULL;
- if (decl_ctx == NULL)
+ ClassTemplateDecl *class_template_decl = nullptr;
+ if (decl_ctx == nullptr)
decl_ctx = ast->getTranslationUnitDecl();
IdentifierInfo &identifier_info = ast->Idents.get(class_name);
@@ -1337,7 +1358,7 @@ ClangASTContext::CreateClassTemplateDecl (DeclContext *decl_ctx,
decl_name,
template_param_list,
template_cxx_decl,
- NULL);
+ nullptr);
if (class_template_decl)
{
@@ -1373,7 +1394,7 @@ ClangASTContext::CreateClassTemplateSpecializationDecl (DeclContext *decl_ctx,
class_template_decl,
&template_param_infos.args.front(),
template_param_infos.args.size(),
- NULL);
+ nullptr);
class_template_specialization_decl->setSpecializationKind(TSK_ExplicitSpecialization);
@@ -1392,222 +1413,6 @@ ClangASTContext::CreateClassTemplateSpecializationType (ClassTemplateSpecializat
return ClangASTType();
}
-static bool
-IsOperator (const char *name, OverloadedOperatorKind &op_kind)
-{
- if (name == NULL || name[0] == '\0')
- return false;
-
-#define OPERATOR_PREFIX "operator"
-#define OPERATOR_PREFIX_LENGTH (sizeof (OPERATOR_PREFIX) - 1)
-
- const char *post_op_name = NULL;
-
- bool no_space = true;
-
- if (::strncmp(name, OPERATOR_PREFIX, OPERATOR_PREFIX_LENGTH))
- return false;
-
- post_op_name = name + OPERATOR_PREFIX_LENGTH;
-
- if (post_op_name[0] == ' ')
- {
- post_op_name++;
- no_space = false;
- }
-
-#undef OPERATOR_PREFIX
-#undef OPERATOR_PREFIX_LENGTH
-
- // This is an operator, set the overloaded operator kind to invalid
- // in case this is a conversion operator...
- op_kind = NUM_OVERLOADED_OPERATORS;
-
- switch (post_op_name[0])
- {
- default:
- if (no_space)
- return false;
- break;
- case 'n':
- if (no_space)
- return false;
- if (strcmp (post_op_name, "new") == 0)
- op_kind = OO_New;
- else if (strcmp (post_op_name, "new[]") == 0)
- op_kind = OO_Array_New;
- break;
-
- case 'd':
- if (no_space)
- return false;
- if (strcmp (post_op_name, "delete") == 0)
- op_kind = OO_Delete;
- else if (strcmp (post_op_name, "delete[]") == 0)
- op_kind = OO_Array_Delete;
- break;
-
- case '+':
- if (post_op_name[1] == '\0')
- op_kind = OO_Plus;
- else if (post_op_name[2] == '\0')
- {
- if (post_op_name[1] == '=')
- op_kind = OO_PlusEqual;
- else if (post_op_name[1] == '+')
- op_kind = OO_PlusPlus;
- }
- break;
-
- case '-':
- if (post_op_name[1] == '\0')
- op_kind = OO_Minus;
- else if (post_op_name[2] == '\0')
- {
- switch (post_op_name[1])
- {
- case '=': op_kind = OO_MinusEqual; break;
- case '-': op_kind = OO_MinusMinus; break;
- case '>': op_kind = OO_Arrow; break;
- }
- }
- else if (post_op_name[3] == '\0')
- {
- if (post_op_name[2] == '*')
- op_kind = OO_ArrowStar; break;
- }
- break;
-
- case '*':
- if (post_op_name[1] == '\0')
- op_kind = OO_Star;
- else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = OO_StarEqual;
- break;
-
- case '/':
- if (post_op_name[1] == '\0')
- op_kind = OO_Slash;
- else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = OO_SlashEqual;
- break;
-
- case '%':
- if (post_op_name[1] == '\0')
- op_kind = OO_Percent;
- else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = OO_PercentEqual;
- break;
-
-
- case '^':
- if (post_op_name[1] == '\0')
- op_kind = OO_Caret;
- else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = OO_CaretEqual;
- break;
-
- case '&':
- if (post_op_name[1] == '\0')
- op_kind = OO_Amp;
- else if (post_op_name[2] == '\0')
- {
- switch (post_op_name[1])
- {
- case '=': op_kind = OO_AmpEqual; break;
- case '&': op_kind = OO_AmpAmp; break;
- }
- }
- break;
-
- case '|':
- if (post_op_name[1] == '\0')
- op_kind = OO_Pipe;
- else if (post_op_name[2] == '\0')
- {
- switch (post_op_name[1])
- {
- case '=': op_kind = OO_PipeEqual; break;
- case '|': op_kind = OO_PipePipe; break;
- }
- }
- break;
-
- case '~':
- if (post_op_name[1] == '\0')
- op_kind = OO_Tilde;
- break;
-
- case '!':
- if (post_op_name[1] == '\0')
- op_kind = OO_Exclaim;
- else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = OO_ExclaimEqual;
- break;
-
- case '=':
- if (post_op_name[1] == '\0')
- op_kind = OO_Equal;
- else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = OO_EqualEqual;
- break;
-
- case '<':
- if (post_op_name[1] == '\0')
- op_kind = OO_Less;
- else if (post_op_name[2] == '\0')
- {
- switch (post_op_name[1])
- {
- case '<': op_kind = OO_LessLess; break;
- case '=': op_kind = OO_LessEqual; break;
- }
- }
- else if (post_op_name[3] == '\0')
- {
- if (post_op_name[2] == '=')
- op_kind = OO_LessLessEqual;
- }
- break;
-
- case '>':
- if (post_op_name[1] == '\0')
- op_kind = OO_Greater;
- else if (post_op_name[2] == '\0')
- {
- switch (post_op_name[1])
- {
- case '>': op_kind = OO_GreaterGreater; break;
- case '=': op_kind = OO_GreaterEqual; break;
- }
- }
- else if (post_op_name[1] == '>' &&
- post_op_name[2] == '=' &&
- post_op_name[3] == '\0')
- {
- op_kind = OO_GreaterGreaterEqual;
- }
- break;
-
- case ',':
- if (post_op_name[1] == '\0')
- op_kind = OO_Comma;
- break;
-
- case '(':
- if (post_op_name[1] == ')' && post_op_name[2] == '\0')
- op_kind = OO_Call;
- break;
-
- case '[':
- if (post_op_name[1] == ']' && post_op_name[2] == '\0')
- op_kind = OO_Subscript;
- break;
- }
-
- return true;
-}
-
static inline bool
check_op_param (uint32_t op_kind, bool unary, bool binary, uint32_t num_params)
{
@@ -1615,7 +1420,7 @@ check_op_param (uint32_t op_kind, bool unary, bool binary, uint32_t num_params)
if(op_kind == OO_Call)
return true;
- // The parameter count doens't include "this"
+ // The parameter count doesn't include "this"
if (num_params == 0)
return unary;
if (num_params == 1)
@@ -1686,7 +1491,7 @@ ClangASTContext::FieldIsBitfield
uint32_t& bitfield_bit_size
)
{
- if (ast == NULL || field == NULL)
+ if (ast == nullptr || field == nullptr)
return false;
if (field->isBitField())
@@ -1708,7 +1513,7 @@ ClangASTContext::FieldIsBitfield
bool
ClangASTContext::RecordHasFields (const RecordDecl *record_decl)
{
- if (record_decl == NULL)
+ if (record_decl == nullptr)
return false;
if (!record_decl->field_empty())
@@ -1744,16 +1549,16 @@ ClangASTContext::CreateObjCClass
)
{
ASTContext *ast = getASTContext();
- assert (ast != NULL);
+ assert (ast != nullptr);
assert (name && name[0]);
- if (decl_ctx == NULL)
+ if (decl_ctx == nullptr)
decl_ctx = ast->getTranslationUnitDecl();
ObjCInterfaceDecl *decl = ObjCInterfaceDecl::Create (*ast,
decl_ctx,
SourceLocation(),
&ast->Idents.get(name),
- NULL,
+ nullptr,
SourceLocation(),
/*isForwardDecl,*/
isInternal);
@@ -1804,10 +1609,10 @@ ClangASTContext::GetNumBaseClasses (const CXXRecordDecl *cxx_record_decl, bool o
NamespaceDecl *
ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *decl_ctx)
{
- NamespaceDecl *namespace_decl = NULL;
+ NamespaceDecl *namespace_decl = nullptr;
ASTContext *ast = getASTContext();
TranslationUnitDecl *translation_unit_decl = ast->getTranslationUnitDecl ();
- if (decl_ctx == NULL)
+ if (decl_ctx == nullptr)
decl_ctx = translation_unit_decl;
if (name)
@@ -1828,7 +1633,7 @@ ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *d
SourceLocation(),
SourceLocation(),
&identifier_info,
- NULL);
+ nullptr);
decl_ctx->addDecl (namespace_decl);
}
@@ -1845,8 +1650,8 @@ ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *d
false,
SourceLocation(),
SourceLocation(),
- NULL,
- NULL);
+ nullptr,
+ nullptr);
translation_unit_decl->setAnonymousNamespace (namespace_decl);
translation_unit_decl->addDecl (namespace_decl);
assert (namespace_decl == translation_unit_decl->getAnonymousNamespace());
@@ -1864,8 +1669,8 @@ ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *d
false,
SourceLocation(),
SourceLocation(),
- NULL,
- NULL);
+ nullptr,
+ nullptr);
parent_namespace_decl->setAnonymousNamespace (namespace_decl);
parent_namespace_decl->addDecl (namespace_decl);
assert (namespace_decl == parent_namespace_decl->getAnonymousNamespace());
@@ -1910,9 +1715,9 @@ ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx,
int storage,
bool is_inline)
{
- FunctionDecl *func_decl = NULL;
+ FunctionDecl *func_decl = nullptr;
ASTContext *ast = getASTContext();
- if (decl_ctx == NULL)
+ if (decl_ctx == nullptr)
decl_ctx = ast->getTranslationUnitDecl();
@@ -1927,7 +1732,7 @@ ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx,
SourceLocation(),
DeclarationName (&ast->Idents.get(name)),
function_clang_type.GetQualType(),
- NULL,
+ nullptr,
(FunctionDecl::StorageClass)storage,
is_inline,
hasWrittenPrototype,
@@ -1941,7 +1746,7 @@ ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx,
SourceLocation(),
DeclarationName (),
function_clang_type.GetQualType(),
- NULL,
+ nullptr,
(FunctionDecl::StorageClass)storage,
is_inline,
hasWrittenPrototype,
@@ -1965,7 +1770,7 @@ ClangASTContext::CreateFunctionType (ASTContext *ast,
bool is_variadic,
unsigned type_quals)
{
- assert (ast != NULL);
+ assert (ast != nullptr);
std::vector<QualType> qual_type_args;
for (unsigned i=0; i<num_args; ++i)
qual_type_args.push_back (args[i].GetQualType());
@@ -1973,12 +1778,10 @@ ClangASTContext::CreateFunctionType (ASTContext *ast,
// TODO: Detect calling convention in DWARF?
FunctionProtoType::ExtProtoInfo proto_info;
proto_info.Variadic = is_variadic;
- proto_info.ExceptionSpecType = EST_None;
+ proto_info.ExceptionSpec = EST_None;
proto_info.TypeQuals = type_quals;
proto_info.RefQualifier = RQ_None;
- proto_info.NumExceptions = 0;
- proto_info.Exceptions = NULL;
-
+
return ClangASTType (ast, ast->getFunctionType (result_type.GetQualType(),
qual_type_args,
proto_info).getAsOpaquePtr());
@@ -1988,16 +1791,16 @@ ParmVarDecl *
ClangASTContext::CreateParameterDeclaration (const char *name, const ClangASTType &param_type, int storage)
{
ASTContext *ast = getASTContext();
- assert (ast != NULL);
+ assert (ast != nullptr);
return ParmVarDecl::Create(*ast,
ast->getTranslationUnitDecl(),
SourceLocation(),
SourceLocation(),
- name && name[0] ? &ast->Idents.get(name) : NULL,
+ name && name[0] ? &ast->Idents.get(name) : nullptr,
param_type.GetQualType(),
- NULL,
+ nullptr,
(VarDecl::StorageClass)storage,
- 0);
+ nullptr);
}
void
@@ -2018,7 +1821,7 @@ ClangASTContext::CreateArrayType (const ClangASTType &element_type,
if (element_type.IsValid())
{
ASTContext *ast = getASTContext();
- assert (ast != NULL);
+ assert (ast != nullptr);
if (is_vector)
{
@@ -2071,8 +1874,8 @@ ClangASTContext::CreateEnumerationType
decl_ctx,
SourceLocation(),
SourceLocation(),
- name && name[0] ? &ast->Idents.get(name) : NULL,
- NULL,
+ name && name[0] ? &ast->Idents.get(name) : nullptr,
+ nullptr,
false, // IsScoped
false, // IsScopedUsingClassTag
false); // IsFixed
@@ -2131,6 +1934,63 @@ ClangASTContext::CreateEnumerationType
// return false;
//}
+ClangASTType
+ClangASTContext::GetIntTypeFromBitSize (clang::ASTContext *ast,
+ size_t bit_size, bool is_signed)
+{
+ if (ast)
+ {
+ if (is_signed)
+ {
+ if (bit_size == ast->getTypeSize(ast->SignedCharTy))
+ return ClangASTType(ast, ast->SignedCharTy.getAsOpaquePtr());
+
+ if (bit_size == ast->getTypeSize(ast->ShortTy))
+ return ClangASTType(ast, ast->ShortTy.getAsOpaquePtr());
+
+ if (bit_size == ast->getTypeSize(ast->IntTy))
+ return ClangASTType(ast, ast->IntTy.getAsOpaquePtr());
+
+ if (bit_size == ast->getTypeSize(ast->LongTy))
+ return ClangASTType(ast, ast->LongTy.getAsOpaquePtr());
+
+ if (bit_size == ast->getTypeSize(ast->LongLongTy))
+ return ClangASTType(ast, ast->LongLongTy.getAsOpaquePtr());
+
+ if (bit_size == ast->getTypeSize(ast->Int128Ty))
+ return ClangASTType(ast, ast->Int128Ty.getAsOpaquePtr());
+ }
+ else
+ {
+ if (bit_size == ast->getTypeSize(ast->UnsignedCharTy))
+ return ClangASTType(ast, ast->UnsignedCharTy.getAsOpaquePtr());
+
+ if (bit_size == ast->getTypeSize(ast->UnsignedShortTy))
+ return ClangASTType(ast, ast->UnsignedShortTy.getAsOpaquePtr());
+
+ if (bit_size == ast->getTypeSize(ast->UnsignedIntTy))
+ return ClangASTType(ast, ast->UnsignedIntTy.getAsOpaquePtr());
+
+ if (bit_size == ast->getTypeSize(ast->UnsignedLongTy))
+ return ClangASTType(ast, ast->UnsignedLongTy.getAsOpaquePtr());
+
+ if (bit_size == ast->getTypeSize(ast->UnsignedLongLongTy))
+ return ClangASTType(ast, ast->UnsignedLongLongTy.getAsOpaquePtr());
+
+ if (bit_size == ast->getTypeSize(ast->UnsignedInt128Ty))
+ return ClangASTType(ast, ast->UnsignedInt128Ty.getAsOpaquePtr());
+ }
+ }
+ return ClangASTType();
+}
+
+ClangASTType
+ClangASTContext::GetPointerSizedIntType (clang::ASTContext *ast, bool is_signed)
+{
+ if (ast)
+ return GetIntTypeFromBitSize(ast, ast->getTypeSize(ast->VoidPtrTy), is_signed);
+ return ClangASTType();
+}
ClangASTType
ClangASTContext::GetFloatTypeFromBitSize (clang::ASTContext *ast,
@@ -2223,7 +2083,7 @@ ClangASTContext::GetMetadata (clang::ASTContext *ast,
if (external_source && external_source->HasMetadata(object))
return external_source->GetMetadata(object);
else
- return NULL;
+ return nullptr;
}
clang::DeclContext *
diff --git a/source/Symbol/ClangASTImporter.cpp b/source/Symbol/ClangASTImporter.cpp
index afdca97ece27..6579afb2f748 100644
--- a/source/Symbol/ClangASTImporter.cpp
+++ b/source/Symbol/ClangASTImporter.cpp
@@ -106,7 +106,7 @@ ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast,
return result;
}
- return NULL;
+ return nullptr;
}
lldb::clang_type_t
@@ -117,7 +117,7 @@ ClangASTImporter::DeportType (clang::ASTContext *dst_ctx,
MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
if (!minion_sp)
- return NULL;
+ return nullptr;
std::set<NamedDecl *> decls_to_deport;
std::set<NamedDecl *> decls_already_deported;
@@ -130,7 +130,7 @@ ClangASTImporter::DeportType (clang::ASTContext *dst_ctx,
minion_sp->ExecuteDeportWorkQueues();
if (!result)
- return NULL;
+ return nullptr;
return result;
@@ -142,39 +142,36 @@ ClangASTImporter::DeportDecl (clang::ASTContext *dst_ctx,
clang::Decl *decl)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (log)
log->Printf(" [ClangASTImporter] DeportDecl called on (%sDecl*)%p from (ASTContext*)%p to (ASTContex*)%p",
- decl->getDeclKindName(),
- decl,
- src_ctx,
- dst_ctx);
-
+ decl->getDeclKindName(), static_cast<void*>(decl),
+ static_cast<void*>(src_ctx),
+ static_cast<void*>(dst_ctx));
+
MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
-
+
if (!minion_sp)
- return NULL;
-
+ return nullptr;
+
std::set<NamedDecl *> decls_to_deport;
std::set<NamedDecl *> decls_already_deported;
-
+
minion_sp->InitDeportWorkQueues(&decls_to_deport,
&decls_already_deported);
-
+
clang::Decl *result = CopyDecl(dst_ctx, src_ctx, decl);
minion_sp->ExecuteDeportWorkQueues();
-
+
if (!result)
- return NULL;
-
+ return nullptr;
+
if (log)
log->Printf(" [ClangASTImporter] DeportDecl deported (%sDecl*)%p to (%sDecl*)%p",
- decl->getDeclKindName(),
- decl,
- result->getDeclKindName(),
- result);
-
+ decl->getDeclKindName(), static_cast<void*>(decl),
+ result->getDeclKindName(), static_cast<void*>(result));
+
return result;
}
@@ -183,11 +180,10 @@ ClangASTImporter::CompleteDecl (clang::Decl *decl)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- if (log)
+ if (log)
log->Printf(" [ClangASTImporter] CompleteDecl called on (%sDecl*)%p",
- decl->getDeclKindName(),
- decl);
-
+ decl->getDeclKindName(), static_cast<void*>(decl));
+
if (ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl))
{
if (!interface_decl->getDefinition())
@@ -412,9 +408,10 @@ void
ClangASTImporter::ForgetDestination (clang::ASTContext *dst_ast)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (log)
- log->Printf(" [ClangASTImporter] Forgetting destination (ASTContext*)%p", dst_ast);
+ log->Printf(" [ClangASTImporter] Forgetting destination (ASTContext*)%p",
+ static_cast<void*>(dst_ast));
m_metadata_map.erase(dst_ast);
}
@@ -423,17 +420,18 @@ void
ClangASTImporter::ForgetSource (clang::ASTContext *dst_ast, clang::ASTContext *src_ast)
{
ASTContextMetadataSP md = MaybeGetContextMetadata (dst_ast);
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
if (log)
- log->Printf(" [ClangASTImporter] Forgetting source->dest (ASTContext*)%p->(ASTContext*)%p", src_ast, dst_ast);
-
+ log->Printf(" [ClangASTImporter] Forgetting source->dest (ASTContext*)%p->(ASTContext*)%p",
+ static_cast<void*>(src_ast), static_cast<void*>(dst_ast));
+
if (!md)
return;
-
+
md->m_minions.erase(src_ast);
-
+
for (OriginMap::iterator iter = md->m_origins.begin();
iter != md->m_origins.end();
)
@@ -503,8 +501,8 @@ ClangASTImporter::Minion::ExecuteDeportWorkQueues ()
to_context_md->m_origins.erase(decl);
}
- m_decls_to_deport = NULL;
- m_decls_already_deported = NULL;
+ m_decls_to_deport = nullptr;
+ m_decls_already_deported = nullptr;
}
void
@@ -572,64 +570,64 @@ clang::Decl *
ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to)
{
ClangASTMetrics::RegisterClangImport();
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
+ lldb::user_id_t user_id = LLDB_INVALID_UID;
+ ClangASTMetadata *metadata = m_master.GetDeclMetadata(from);
+ if (metadata)
+ user_id = metadata->GetUserID();
+
if (log)
{
- lldb::user_id_t user_id;
- ClangASTMetadata *metadata = m_master.GetDeclMetadata(from);
- if (metadata)
- user_id = metadata->GetUserID();
-
if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from))
{
std::string name_string;
llvm::raw_string_ostream name_stream(name_string);
from_named_decl->printName(name_stream);
name_stream.flush();
-
+
log->Printf(" [ClangASTImporter] Imported (%sDecl*)%p, named %s (from (Decl*)%p), metadata 0x%" PRIx64,
- from->getDeclKindName(),
- to,
- name_string.c_str(),
- from,
+ from->getDeclKindName(), static_cast<void*>(to),
+ name_string.c_str(), static_cast<void*>(from),
user_id);
}
else
{
log->Printf(" [ClangASTImporter] Imported (%sDecl*)%p (from (Decl*)%p), metadata 0x%" PRIx64,
- from->getDeclKindName(),
- to,
- from,
- user_id);
+ from->getDeclKindName(), static_cast<void*>(to),
+ static_cast<void*>(from), user_id);
}
}
ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&to->getASTContext());
ASTContextMetadataSP from_context_md = m_master.MaybeGetContextMetadata(m_source_ctx);
-
+
if (from_context_md)
{
OriginMap &origins = from_context_md->m_origins;
-
+
OriginMap::iterator origin_iter = origins.find(from);
-
+
if (origin_iter != origins.end())
{
- to_context_md->m_origins[to] = origin_iter->second;
-
+ if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
+ user_id != LLDB_INVALID_UID)
+ {
+ to_context_md->m_origins[to] = origin_iter->second;
+ }
+
MinionSP direct_completer = m_master.GetMinion(&to->getASTContext(), origin_iter->second.ctx);
-
+
if (direct_completer.get() != this)
direct_completer->ASTImporter::Imported(origin_iter->second.decl, to);
-
+
if (log)
log->Printf(" [ClangASTImporter] Propagated origin (Decl*)%p/(ASTContext*)%p from (ASTContext*)%p to (ASTContext*)%p",
- origin_iter->second.decl,
- origin_iter->second.ctx,
- &from->getASTContext(),
- &to->getASTContext());
+ static_cast<void*>(origin_iter->second.decl),
+ static_cast<void*>(origin_iter->second.ctx),
+ static_cast<void*>(&from->getASTContext()),
+ static_cast<void*>(&to->getASTContext()));
}
else
{
@@ -638,27 +636,31 @@ ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to)
if (isa<TagDecl>(to) || isa<ObjCInterfaceDecl>(to))
{
NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
-
+
if (!m_decls_already_deported->count(to_named_decl))
m_decls_to_deport->insert(to_named_decl);
}
-
}
- to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
+ if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
+ user_id != LLDB_INVALID_UID)
+ {
+ to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
+ }
+
if (log)
log->Printf(" [ClangASTImporter] Decl has no origin information in (ASTContext*)%p",
- &from->getASTContext());
+ static_cast<void*>(&from->getASTContext()));
}
-
+
if (clang::NamespaceDecl *to_namespace = dyn_cast<clang::NamespaceDecl>(to))
{
clang::NamespaceDecl *from_namespace = dyn_cast<clang::NamespaceDecl>(from);
-
+
NamespaceMetaMap &namespace_maps = from_context_md->m_namespace_maps;
-
+
NamespaceMetaMap::iterator namespace_map_iter = namespace_maps.find(from_namespace);
-
+
if (namespace_map_iter != namespace_maps.end())
to_context_md->m_namespace_maps[to_namespace] = namespace_map_iter->second;
}
@@ -666,21 +668,21 @@ ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to)
else
{
to_context_md->m_origins[to] = DeclOrigin (m_source_ctx, from);
-
+
if (log)
log->Printf(" [ClangASTImporter] Sourced origin (Decl*)%p/(ASTContext*)%p into (ASTContext*)%p",
- from,
- m_source_ctx,
- &to->getASTContext());
+ static_cast<void*>(from),
+ static_cast<void*>(m_source_ctx),
+ static_cast<void*>(&to->getASTContext()));
}
-
+
if (TagDecl *from_tag_decl = dyn_cast<TagDecl>(from))
{
TagDecl *to_tag_decl = dyn_cast<TagDecl>(to);
-
+
to_tag_decl->setHasExternalLexicalStorage();
to_tag_decl->setMustBuildLookupTable();
-
+
if (log)
log->Printf(" [ClangASTImporter] To is a TagDecl - attributes %s%s [%s->%s]",
(to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
@@ -688,32 +690,32 @@ ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to)
(from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"),
(to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"));
}
-
+
if (isa<NamespaceDecl>(from))
{
NamespaceDecl *to_namespace_decl = dyn_cast<NamespaceDecl>(to);
-
+
m_master.BuildNamespaceMap(to_namespace_decl);
-
+
to_namespace_decl->setHasExternalVisibleStorage();
}
-
+
if (isa<ObjCInterfaceDecl>(from))
{
ObjCInterfaceDecl *to_interface_decl = dyn_cast<ObjCInterfaceDecl>(to);
-
+
to_interface_decl->setHasExternalLexicalStorage();
to_interface_decl->setHasExternalVisibleStorage();
-
+
/*to_interface_decl->setExternallyCompleted();*/
-
+
if (log)
log->Printf(" [ClangASTImporter] To is an ObjCInterfaceDecl - attributes %s%s%s",
(to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
(to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""),
(to_interface_decl->hasDefinition() ? " HasDefinition" : ""));
}
-
+
return clang::ASTImporter::Imported(from, to);
}
@@ -722,12 +724,12 @@ clang::Decl *ClangASTImporter::Minion::GetOriginalDecl (clang::Decl *To)
ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&To->getASTContext());
if (!to_context_md)
- return NULL;
+ return nullptr;
OriginMap::iterator iter = to_context_md->m_origins.find(To);
if (iter == to_context_md->m_origins.end())
- return NULL;
+ return nullptr;
return const_cast<clang::Decl*>(iter->second.decl);
}
diff --git a/source/Symbol/ClangASTType.cpp b/source/Symbol/ClangASTType.cpp
index 40f6462ee360..a0878ae442c8 100644
--- a/source/Symbol/ClangASTType.cpp
+++ b/source/Symbol/ClangASTType.cpp
@@ -22,6 +22,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Type.h"
+#include "clang/AST/VTableBuilder.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
@@ -50,11 +51,9 @@
using namespace lldb;
using namespace lldb_private;
-using namespace clang;
-using namespace llvm;
static bool
-GetCompleteQualType (ASTContext *ast, QualType qual_type, bool allow_completion = true)
+GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool allow_completion = true)
{
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
@@ -63,7 +62,7 @@ GetCompleteQualType (ASTContext *ast, QualType qual_type, bool allow_completion
case clang::Type::IncompleteArray:
case clang::Type::VariableArray:
{
- const ArrayType *array_type = dyn_cast<ArrayType>(qual_type.getTypePtr());
+ const clang::ArrayType *array_type = llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr());
if (array_type)
return GetCompleteQualType (ast, array_type->getElementType(), allow_completion);
@@ -73,10 +72,10 @@ GetCompleteQualType (ASTContext *ast, QualType qual_type, bool allow_completion
case clang::Type::Record:
case clang::Type::Enum:
{
- const TagType *tag_type = dyn_cast<TagType>(qual_type.getTypePtr());
+ const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
if (tag_type)
{
- TagDecl *tag_decl = tag_type->getDecl();
+ clang::TagDecl *tag_decl = tag_type->getDecl();
if (tag_decl)
{
if (tag_decl->isCompleteDefinition())
@@ -89,7 +88,7 @@ GetCompleteQualType (ASTContext *ast, QualType qual_type, bool allow_completion
{
if (ast)
{
- ExternalASTSource *external_ast_source = ast->getExternalSource();
+ clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
if (external_ast_source)
{
external_ast_source->CompleteType(tag_decl);
@@ -107,10 +106,10 @@ GetCompleteQualType (ASTContext *ast, QualType qual_type, bool allow_completion
case clang::Type::ObjCObject:
case clang::Type::ObjCInterface:
{
- const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type);
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
// We currently can't complete objective C types through the newly added ASTContext
// because it only supports TagDecl objects right now...
if (class_interface_decl)
@@ -125,7 +124,7 @@ GetCompleteQualType (ASTContext *ast, QualType qual_type, bool allow_completion
{
if (ast)
{
- ExternalASTSource *external_ast_source = ast->getExternalSource();
+ clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
if (external_ast_source)
{
external_ast_source->CompleteType (class_interface_decl);
@@ -140,13 +139,13 @@ GetCompleteQualType (ASTContext *ast, QualType qual_type, bool allow_completion
break;
case clang::Type::Typedef:
- return GetCompleteQualType (ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType(), allow_completion);
+ return GetCompleteQualType (ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType(), allow_completion);
case clang::Type::Elaborated:
- return GetCompleteQualType (ast, cast<ElaboratedType>(qual_type)->getNamedType(), allow_completion);
+ return GetCompleteQualType (ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(), allow_completion);
case clang::Type::Paren:
- return GetCompleteQualType (ast, cast<ParenType>(qual_type)->desugar(), allow_completion);
+ return GetCompleteQualType (ast, llvm::cast<clang::ParenType>(qual_type)->desugar(), allow_completion);
default:
break;
@@ -155,18 +154,18 @@ GetCompleteQualType (ASTContext *ast, QualType qual_type, bool allow_completion
return true;
}
-static ObjCIvarDecl::AccessControl
+static clang::ObjCIvarDecl::AccessControl
ConvertAccessTypeToObjCIvarAccessControl (AccessType access)
{
switch (access)
{
- case eAccessNone: return ObjCIvarDecl::None;
- case eAccessPublic: return ObjCIvarDecl::Public;
- case eAccessPrivate: return ObjCIvarDecl::Private;
- case eAccessProtected: return ObjCIvarDecl::Protected;
- case eAccessPackage: return ObjCIvarDecl::Package;
+ case eAccessNone: return clang::ObjCIvarDecl::None;
+ case eAccessPublic: return clang::ObjCIvarDecl::Public;
+ case eAccessPrivate: return clang::ObjCIvarDecl::Private;
+ case eAccessProtected: return clang::ObjCIvarDecl::Protected;
+ case eAccessPackage: return clang::ObjCIvarDecl::Package;
}
- return ObjCIvarDecl::None;
+ return clang::ObjCIvarDecl::None;
}
//----------------------------------------------------------------------
@@ -194,7 +193,7 @@ ClangASTType::IsAggregateType () const
if (!IsValid())
return false;
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
@@ -209,11 +208,11 @@ ClangASTType::IsAggregateType () const
case clang::Type::ObjCInterface:
return true;
case clang::Type::Elaborated:
- return ClangASTType(m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).IsAggregateType();
+ return ClangASTType(m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsAggregateType();
case clang::Type::Typedef:
- return ClangASTType(m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsAggregateType();
+ return ClangASTType(m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsAggregateType();
case clang::Type::Paren:
- return ClangASTType(m_ast, cast<ParenType>(qual_type)->desugar()).IsAggregateType();
+ return ClangASTType(m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsAggregateType();
default:
break;
}
@@ -228,7 +227,7 @@ ClangASTType::IsArrayType (ClangASTType *element_type_ptr,
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
@@ -238,14 +237,14 @@ ClangASTType::IsArrayType (ClangASTType *element_type_ptr,
case clang::Type::ConstantArray:
if (element_type_ptr)
- element_type_ptr->SetClangType (m_ast, cast<ConstantArrayType>(qual_type)->getElementType());
+ element_type_ptr->SetClangType (m_ast, llvm::cast<clang::ConstantArrayType>(qual_type)->getElementType());
if (size)
- *size = cast<ConstantArrayType>(qual_type)->getSize().getLimitedValue(ULLONG_MAX);
+ *size = llvm::cast<clang::ConstantArrayType>(qual_type)->getSize().getLimitedValue(ULLONG_MAX);
return true;
case clang::Type::IncompleteArray:
if (element_type_ptr)
- element_type_ptr->SetClangType (m_ast, cast<IncompleteArrayType>(qual_type)->getElementType());
+ element_type_ptr->SetClangType (m_ast, llvm::cast<clang::IncompleteArrayType>(qual_type)->getElementType());
if (size)
*size = 0;
if (is_incomplete)
@@ -254,28 +253,28 @@ ClangASTType::IsArrayType (ClangASTType *element_type_ptr,
case clang::Type::VariableArray:
if (element_type_ptr)
- element_type_ptr->SetClangType (m_ast, cast<VariableArrayType>(qual_type)->getElementType());
+ element_type_ptr->SetClangType (m_ast, llvm::cast<clang::VariableArrayType>(qual_type)->getElementType());
if (size)
*size = 0;
return true;
case clang::Type::DependentSizedArray:
if (element_type_ptr)
- element_type_ptr->SetClangType (m_ast, cast<DependentSizedArrayType>(qual_type)->getElementType());
+ element_type_ptr->SetClangType (m_ast, llvm::cast<clang::DependentSizedArrayType>(qual_type)->getElementType());
if (size)
*size = 0;
return true;
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsArrayType (element_type_ptr,
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsArrayType (element_type_ptr,
size,
is_incomplete);
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).IsArrayType (element_type_ptr,
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsArrayType (element_type_ptr,
size,
is_incomplete);
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).IsArrayType (element_type_ptr,
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsArrayType (element_type_ptr,
size,
is_incomplete);
}
@@ -352,7 +351,7 @@ ClangASTType::IsCStringType (uint32_t &length) const
{
// We know the size of the array and it could be a C string
// since it is an array of characters
- length = cast<ConstantArrayType>(GetCanonicalQualType().getTypePtr())->getSize().getLimitedValue();
+ length = llvm::cast<clang::ConstantArrayType>(GetCanonicalQualType().getTypePtr())->getSize().getLimitedValue();
}
return true;
@@ -366,7 +365,7 @@ ClangASTType::IsFunctionType (bool *is_variadic_ptr) const
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
if (qual_type->isFunctionType())
{
@@ -387,16 +386,16 @@ ClangASTType::IsFunctionType (bool *is_variadic_ptr) const
default:
break;
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsFunctionType();
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsFunctionType();
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).IsFunctionType();
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsFunctionType();
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).IsFunctionType();
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsFunctionType();
case clang::Type::LValueReference:
case clang::Type::RValueReference:
{
- const ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr());
+ const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
if (reference_type)
return ClangASTType (m_ast, reference_type->getPointeeType()).IsFunctionType();
}
@@ -406,13 +405,109 @@ ClangASTType::IsFunctionType (bool *is_variadic_ptr) const
return false;
}
+// Used to detect "Homogeneous Floating-point Aggregates"
+uint32_t
+ClangASTType::IsHomogeneousAggregate (ClangASTType* base_type_ptr) const
+{
+ if (!IsValid())
+ return 0;
+
+ clang::QualType qual_type(GetCanonicalQualType());
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType ())
+ {
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ if (cxx_record_decl->getNumBases() ||
+ cxx_record_decl->isDynamicClass())
+ return 0;
+ }
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ if (record_type)
+ {
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+ if (record_decl)
+ {
+ // We are looking for a structure that contains only floating point types
+ clang::RecordDecl::field_iterator field_pos, field_end = record_decl->field_end();
+ uint32_t num_fields = 0;
+ bool is_hva = false;
+ bool is_hfa = false;
+ clang::QualType base_qual_type;
+ for (field_pos = record_decl->field_begin(); field_pos != field_end; ++field_pos)
+ {
+ clang::QualType field_qual_type = field_pos->getType();
+ if (field_qual_type->isFloatingType())
+ {
+ if (field_qual_type->isComplexType())
+ return 0;
+ else
+ {
+ if (num_fields == 0)
+ base_qual_type = field_qual_type;
+ else
+ {
+ if (is_hva)
+ return 0;
+ is_hfa = true;
+ if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr())
+ return 0;
+ }
+ }
+ }
+ else if (field_qual_type->isVectorType() || field_qual_type->isExtVectorType())
+ {
+ const clang::VectorType *array = llvm::cast<clang::VectorType>(field_qual_type.getTypePtr());
+ if (array && array->getNumElements() <= 4)
+ {
+ if (num_fields == 0)
+ base_qual_type = array->getElementType();
+ else
+ {
+ if (is_hfa)
+ return 0;
+ is_hva = true;
+ if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr())
+ return 0;
+ }
+ }
+ else
+ return 0;
+ }
+ else
+ return 0;
+ ++num_fields;
+ }
+ if (base_type_ptr)
+ *base_type_ptr = ClangASTType (m_ast, base_qual_type);
+ return num_fields;
+ }
+ }
+ }
+ break;
+
+ case clang::Type::Typedef:
+ return ClangASTType(m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsHomogeneousAggregate (base_type_ptr);
+
+ case clang::Type::Elaborated:
+ return ClangASTType(m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsHomogeneousAggregate (base_type_ptr);
+ default:
+ break;
+ }
+ return 0;
+}
+
size_t
ClangASTType::GetNumberOfFunctionArguments () const
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
- const FunctionProtoType* func = dyn_cast<FunctionProtoType>(qual_type.getTypePtr());
+ clang::QualType qual_type (GetCanonicalQualType());
+ const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
if (func)
return func->getNumParams();
}
@@ -424,8 +519,8 @@ ClangASTType::GetFunctionArgumentAtIndex (const size_t index)
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
- const FunctionProtoType* func = dyn_cast<FunctionProtoType>(qual_type.getTypePtr());
+ clang::QualType qual_type (GetCanonicalQualType());
+ const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
if (func)
{
if (index < func->getNumParams())
@@ -440,7 +535,7 @@ ClangASTType::IsFunctionPointerType () const
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
if (qual_type->isFunctionPointerType())
return true;
@@ -451,16 +546,16 @@ ClangASTType::IsFunctionPointerType () const
default:
break;
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsFunctionPointerType();
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsFunctionPointerType();
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).IsFunctionPointerType();
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsFunctionPointerType();
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).IsFunctionPointerType();
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsFunctionPointerType();
case clang::Type::LValueReference:
case clang::Type::RValueReference:
{
- const ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr());
+ const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
if (reference_type)
return ClangASTType (m_ast, reference_type->getPointeeType()).IsFunctionPointerType();
}
@@ -477,8 +572,8 @@ ClangASTType::IsIntegerType (bool &is_signed) const
if (!IsValid())
return false;
- QualType qual_type (GetCanonicalQualType());
- const BuiltinType *builtin_type = dyn_cast<BuiltinType>(qual_type->getCanonicalTypeInternal());
+ clang::QualType qual_type (GetCanonicalQualType());
+ const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());
if (builtin_type)
{
@@ -497,12 +592,12 @@ ClangASTType::IsPointerType (ClangASTType *pointee_type) const
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Builtin:
- switch (cast<clang::BuiltinType>(qual_type)->getKind())
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
{
default:
break;
@@ -513,26 +608,26 @@ ClangASTType::IsPointerType (ClangASTType *pointee_type) const
return false;
case clang::Type::ObjCObjectPointer:
if (pointee_type)
- pointee_type->SetClangType (m_ast, cast<ObjCObjectPointerType>(qual_type)->getPointeeType());
+ pointee_type->SetClangType (m_ast, llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType());
return true;
case clang::Type::BlockPointer:
if (pointee_type)
- pointee_type->SetClangType (m_ast, cast<BlockPointerType>(qual_type)->getPointeeType());
+ pointee_type->SetClangType (m_ast, llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType());
return true;
case clang::Type::Pointer:
if (pointee_type)
- pointee_type->SetClangType (m_ast, cast<PointerType>(qual_type)->getPointeeType());
+ pointee_type->SetClangType (m_ast, llvm::cast<clang::PointerType>(qual_type)->getPointeeType());
return true;
case clang::Type::MemberPointer:
if (pointee_type)
- pointee_type->SetClangType (m_ast, cast<MemberPointerType>(qual_type)->getPointeeType());
+ pointee_type->SetClangType (m_ast, llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType());
return true;
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsPointerType(pointee_type);
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsPointerType(pointee_type);
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).IsPointerType(pointee_type);
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsPointerType(pointee_type);
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).IsPointerType(pointee_type);
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsPointerType(pointee_type);
default:
break;
}
@@ -548,12 +643,12 @@ ClangASTType::IsPointerOrReferenceType (ClangASTType *pointee_type) const
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Builtin:
- switch (cast<clang::BuiltinType>(qual_type)->getKind())
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
{
default:
break;
@@ -564,34 +659,34 @@ ClangASTType::IsPointerOrReferenceType (ClangASTType *pointee_type) const
return false;
case clang::Type::ObjCObjectPointer:
if (pointee_type)
- pointee_type->SetClangType(m_ast, cast<ObjCObjectPointerType>(qual_type)->getPointeeType());
+ pointee_type->SetClangType(m_ast, llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType());
return true;
case clang::Type::BlockPointer:
if (pointee_type)
- pointee_type->SetClangType(m_ast, cast<BlockPointerType>(qual_type)->getPointeeType());
+ pointee_type->SetClangType(m_ast, llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType());
return true;
case clang::Type::Pointer:
if (pointee_type)
- pointee_type->SetClangType(m_ast, cast<PointerType>(qual_type)->getPointeeType());
+ pointee_type->SetClangType(m_ast, llvm::cast<clang::PointerType>(qual_type)->getPointeeType());
return true;
case clang::Type::MemberPointer:
if (pointee_type)
- pointee_type->SetClangType(m_ast, cast<MemberPointerType>(qual_type)->getPointeeType());
+ pointee_type->SetClangType(m_ast, llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType());
return true;
case clang::Type::LValueReference:
if (pointee_type)
- pointee_type->SetClangType(m_ast, cast<LValueReferenceType>(qual_type)->desugar());
+ pointee_type->SetClangType(m_ast, llvm::cast<clang::LValueReferenceType>(qual_type)->desugar());
return true;
case clang::Type::RValueReference:
if (pointee_type)
- pointee_type->SetClangType(m_ast, cast<LValueReferenceType>(qual_type)->desugar());
+ pointee_type->SetClangType(m_ast, llvm::cast<clang::RValueReferenceType>(qual_type)->desugar());
return true;
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsPointerOrReferenceType(pointee_type);
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsPointerOrReferenceType(pointee_type);
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).IsPointerOrReferenceType(pointee_type);
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsPointerOrReferenceType(pointee_type);
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).IsPointerOrReferenceType(pointee_type);
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsPointerOrReferenceType(pointee_type);
default:
break;
}
@@ -603,29 +698,33 @@ ClangASTType::IsPointerOrReferenceType (ClangASTType *pointee_type) const
bool
-ClangASTType::IsReferenceType (ClangASTType *pointee_type) const
+ClangASTType::IsReferenceType (ClangASTType *pointee_type, bool* is_rvalue) const
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::LValueReference:
if (pointee_type)
- pointee_type->SetClangType(m_ast, cast<LValueReferenceType>(qual_type)->desugar());
+ pointee_type->SetClangType(m_ast, llvm::cast<clang::LValueReferenceType>(qual_type)->desugar());
+ if (is_rvalue)
+ *is_rvalue = false;
return true;
case clang::Type::RValueReference:
if (pointee_type)
- pointee_type->SetClangType(m_ast, cast<LValueReferenceType>(qual_type)->desugar());
+ pointee_type->SetClangType(m_ast, llvm::cast<clang::RValueReferenceType>(qual_type)->desugar());
+ if (is_rvalue)
+ *is_rvalue = true;
return true;
case clang::Type::Typedef:
- return ClangASTType(m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsReferenceType(pointee_type);
+ return ClangASTType(m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsReferenceType(pointee_type, is_rvalue);
case clang::Type::Elaborated:
- return ClangASTType(m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).IsReferenceType(pointee_type);
+ return ClangASTType(m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsReferenceType(pointee_type, is_rvalue);
case clang::Type::Paren:
- return ClangASTType(m_ast, cast<clang::ParenType>(qual_type)->desugar()).IsReferenceType(pointee_type);
+ return ClangASTType(m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsReferenceType(pointee_type, is_rvalue);
default:
break;
@@ -641,19 +740,19 @@ ClangASTType::IsFloatingPointType (uint32_t &count, bool &is_complex) const
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(qual_type->getCanonicalTypeInternal()))
+ if (const clang::BuiltinType *BT = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal()))
{
clang::BuiltinType::Kind kind = BT->getKind();
- if (kind >= BuiltinType::Float && kind <= BuiltinType::LongDouble)
+ if (kind >= clang::BuiltinType::Float && kind <= clang::BuiltinType::LongDouble)
{
count = 1;
is_complex = false;
return true;
}
}
- else if (const ComplexType *CT = dyn_cast<ComplexType>(qual_type->getCanonicalTypeInternal()))
+ else if (const clang::ComplexType *CT = llvm::dyn_cast<clang::ComplexType>(qual_type->getCanonicalTypeInternal()))
{
if (ClangASTType (m_ast, CT->getElementType()).IsFloatingPointType (count, is_complex))
{
@@ -662,7 +761,7 @@ ClangASTType::IsFloatingPointType (uint32_t &count, bool &is_complex) const
return true;
}
}
- else if (const VectorType *VT = dyn_cast<VectorType>(qual_type->getCanonicalTypeInternal()))
+ else if (const clang::VectorType *VT = llvm::dyn_cast<clang::VectorType>(qual_type->getCanonicalTypeInternal()))
{
if (ClangASTType (m_ast, VT->getElementType()).IsFloatingPointType (count, is_complex))
{
@@ -684,23 +783,23 @@ ClangASTType::IsDefined() const
if (!IsValid())
return false;
- QualType qual_type(GetQualType());
- const TagType *tag_type = dyn_cast<TagType>(qual_type.getTypePtr());
+ clang::QualType qual_type(GetQualType());
+ const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
if (tag_type)
{
- TagDecl *tag_decl = tag_type->getDecl();
+ clang::TagDecl *tag_decl = tag_type->getDecl();
if (tag_decl)
return tag_decl->isCompleteDefinition();
return false;
}
else
{
- const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type);
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
if (class_interface_decl)
- return class_interface_decl->getDefinition() != NULL;
+ return class_interface_decl->getDefinition() != nullptr;
return false;
}
}
@@ -712,9 +811,9 @@ ClangASTType::IsObjCClassType () const
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
- const ObjCObjectPointerType *obj_pointer_type = dyn_cast<ObjCObjectPointerType>(qual_type);
+ const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type);
if (obj_pointer_type)
return obj_pointer_type->isObjCClassType();
@@ -735,18 +834,18 @@ ClangASTType::IsPolymorphicClass () const
{
if (IsValid())
{
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Record:
if (GetCompleteType())
{
- const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
- const RecordDecl *record_decl = record_type->getDecl();
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
if (record_decl)
{
- const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
if (cxx_record_decl)
return cxx_record_decl->isPolymorphic();
}
@@ -765,16 +864,16 @@ ClangASTType::IsPossibleDynamicType (ClangASTType *dynamic_pointee_type,
bool check_cplusplus,
bool check_objc) const
{
- QualType pointee_qual_type;
+ clang::QualType pointee_qual_type;
if (m_type)
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
bool success = false;
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Builtin:
- if (check_objc && cast<BuiltinType>(qual_type)->getKind() == BuiltinType::ObjCId)
+ if (check_objc && llvm::cast<clang::BuiltinType>(qual_type)->getKind() == clang::BuiltinType::ObjCId)
{
if (dynamic_pointee_type)
dynamic_pointee_type->SetClangType(m_ast, m_type);
@@ -786,37 +885,37 @@ ClangASTType::IsPossibleDynamicType (ClangASTType *dynamic_pointee_type,
if (check_objc)
{
if (dynamic_pointee_type)
- dynamic_pointee_type->SetClangType(m_ast, cast<ObjCObjectPointerType>(qual_type)->getPointeeType());
+ dynamic_pointee_type->SetClangType(m_ast, llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType());
return true;
}
break;
case clang::Type::Pointer:
- pointee_qual_type = cast<PointerType>(qual_type)->getPointeeType();
+ pointee_qual_type = llvm::cast<clang::PointerType>(qual_type)->getPointeeType();
success = true;
break;
case clang::Type::LValueReference:
case clang::Type::RValueReference:
- pointee_qual_type = cast<ReferenceType>(qual_type)->getPointeeType();
+ pointee_qual_type = llvm::cast<clang::ReferenceType>(qual_type)->getPointeeType();
success = true;
break;
case clang::Type::Typedef:
return ClangASTType (m_ast,
- cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsPossibleDynamicType (dynamic_pointee_type,
+ llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsPossibleDynamicType (dynamic_pointee_type,
check_cplusplus,
check_objc);
case clang::Type::Elaborated:
return ClangASTType (m_ast,
- cast<ElaboratedType>(qual_type)->getNamedType()).IsPossibleDynamicType (dynamic_pointee_type,
+ llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsPossibleDynamicType (dynamic_pointee_type,
check_cplusplus,
check_objc);
case clang::Type::Paren:
return ClangASTType (m_ast,
- cast<ParenType>(qual_type)->desugar()).IsPossibleDynamicType (dynamic_pointee_type,
+ llvm::cast<clang::ParenType>(qual_type)->desugar()).IsPossibleDynamicType (dynamic_pointee_type,
check_cplusplus,
check_objc);
default:
@@ -832,55 +931,55 @@ ClangASTType::IsPossibleDynamicType (ClangASTType *dynamic_pointee_type,
switch (pointee_type_class)
{
case clang::Type::Builtin:
- switch (cast<BuiltinType>(pointee_qual_type)->getKind())
+ switch (llvm::cast<clang::BuiltinType>(pointee_qual_type)->getKind())
{
- case BuiltinType::UnknownAny:
- case BuiltinType::Void:
+ case clang::BuiltinType::UnknownAny:
+ case clang::BuiltinType::Void:
if (dynamic_pointee_type)
dynamic_pointee_type->SetClangType(m_ast, pointee_qual_type);
return true;
- case BuiltinType::NullPtr:
- case BuiltinType::Bool:
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::WChar_U:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::UShort:
- case BuiltinType::UInt:
- case BuiltinType::ULong:
- case BuiltinType::ULongLong:
- case BuiltinType::UInt128:
- case BuiltinType::Char_S:
- case BuiltinType::SChar:
- case BuiltinType::WChar_S:
- case BuiltinType::Short:
- case BuiltinType::Int:
- case BuiltinType::Long:
- case BuiltinType::LongLong:
- case BuiltinType::Int128:
- case BuiltinType::Float:
- case BuiltinType::Double:
- case BuiltinType::LongDouble:
- case BuiltinType::Dependent:
- case BuiltinType::Overload:
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
- case BuiltinType::BoundMember:
- case BuiltinType::Half:
- case BuiltinType::ARCUnbridgedCast:
- case BuiltinType::PseudoObject:
- case BuiltinType::BuiltinFn:
- case BuiltinType::OCLEvent:
- case BuiltinType::OCLImage1d:
- case BuiltinType::OCLImage1dArray:
- case BuiltinType::OCLImage1dBuffer:
- case BuiltinType::OCLImage2d:
- case BuiltinType::OCLImage2dArray:
- case BuiltinType::OCLImage3d:
- case BuiltinType::OCLSampler:
+ case clang::BuiltinType::NullPtr:
+ case clang::BuiltinType::Bool:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
+ case clang::BuiltinType::UShort:
+ case clang::BuiltinType::UInt:
+ case clang::BuiltinType::ULong:
+ case clang::BuiltinType::ULongLong:
+ case clang::BuiltinType::UInt128:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Short:
+ case clang::BuiltinType::Int:
+ case clang::BuiltinType::Long:
+ case clang::BuiltinType::LongLong:
+ case clang::BuiltinType::Int128:
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::LongDouble:
+ case clang::BuiltinType::Dependent:
+ case clang::BuiltinType::Overload:
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ case clang::BuiltinType::ObjCSel:
+ case clang::BuiltinType::BoundMember:
+ case clang::BuiltinType::Half:
+ case clang::BuiltinType::ARCUnbridgedCast:
+ case clang::BuiltinType::PseudoObject:
+ case clang::BuiltinType::BuiltinFn:
+ case clang::BuiltinType::OCLEvent:
+ case clang::BuiltinType::OCLImage1d:
+ case clang::BuiltinType::OCLImage1dArray:
+ case clang::BuiltinType::OCLImage1dBuffer:
+ case clang::BuiltinType::OCLImage2d:
+ case clang::BuiltinType::OCLImage2dArray:
+ case clang::BuiltinType::OCLImage3d:
+ case clang::BuiltinType::OCLSampler:
break;
}
break;
@@ -888,7 +987,7 @@ ClangASTType::IsPossibleDynamicType (ClangASTType *dynamic_pointee_type,
case clang::Type::Record:
if (check_cplusplus)
{
- CXXRecordDecl *cxx_record_decl = pointee_qual_type->getAsCXXRecordDecl();
+ clang::CXXRecordDecl *cxx_record_decl = pointee_qual_type->getAsCXXRecordDecl();
if (cxx_record_decl)
{
bool is_complete = cxx_record_decl->isCompleteDefinition();
@@ -947,7 +1046,7 @@ ClangASTType::IsScalarType () const
if (!IsValid())
return false;
- return (GetTypeInfo (NULL) & eTypeIsScalar) != 0;
+ return (GetTypeInfo (nullptr) & eTypeIsScalar) != 0;
}
bool
@@ -979,7 +1078,7 @@ bool
ClangASTType::IsArrayOfScalarType () const
{
ClangASTType element_type;
- if (IsArrayType(&element_type, NULL, NULL))
+ if (IsArrayType(&element_type, nullptr, nullptr))
return element_type.IsScalarType();
return false;
}
@@ -990,9 +1089,9 @@ ClangASTType::GetCXXClassName (std::string &class_name) const
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
- CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
if (cxx_record_decl)
{
class_name.assign (cxx_record_decl->getIdentifier()->getNameStart());
@@ -1010,8 +1109,8 @@ ClangASTType::IsCXXClassType () const
if (!IsValid())
return false;
- QualType qual_type (GetCanonicalQualType());
- if (qual_type->getAsCXXRecordDecl() != NULL)
+ clang::QualType qual_type (GetCanonicalQualType());
+ if (qual_type->getAsCXXRecordDecl() != nullptr)
return true;
return false;
}
@@ -1021,8 +1120,8 @@ ClangASTType::IsBeingDefined () const
{
if (!IsValid())
return false;
- QualType qual_type (GetCanonicalQualType());
- const clang::TagType *tag_type = dyn_cast<clang::TagType>(qual_type);
+ clang::QualType qual_type (GetCanonicalQualType());
+ const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type);
if (tag_type)
return tag_type->isBeingDefined();
return false;
@@ -1034,7 +1133,7 @@ ClangASTType::IsObjCObjectPointerType (ClangASTType *class_type_ptr)
if (!IsValid())
return false;
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
if (qual_type->isObjCObjectPointerType())
{
@@ -1043,11 +1142,11 @@ ClangASTType::IsObjCObjectPointerType (ClangASTType *class_type_ptr)
if (!qual_type->isObjCClassType() &&
!qual_type->isObjCIdType())
{
- const ObjCObjectPointerType *obj_pointer_type = dyn_cast<ObjCObjectPointerType>(qual_type);
- if (obj_pointer_type == NULL)
+ const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type);
+ if (obj_pointer_type == nullptr)
class_type_ptr->Clear();
else
- class_type_ptr->SetClangType (m_ast, QualType(obj_pointer_type->getInterfaceType(), 0));
+ class_type_ptr->SetClangType (m_ast, clang::QualType(obj_pointer_type->getInterfaceType(), 0));
}
}
return true;
@@ -1063,12 +1162,12 @@ ClangASTType::GetObjCClassName (std::string &class_name)
if (!IsValid())
return false;
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
- const ObjCObjectType *object_type = dyn_cast<ObjCObjectType>(qual_type);
+ const clang::ObjCObjectType *object_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
if (object_type)
{
- const ObjCInterfaceDecl *interface = object_type->getInterface();
+ const clang::ObjCInterfaceDecl *interface = object_type->getInterface();
if (interface)
{
class_name = interface->getNameAsString();
@@ -1127,14 +1226,14 @@ ClangASTType::GetTypeName () const
std::string type_name;
if (IsValid())
{
- PrintingPolicy printing_policy (m_ast->getPrintingPolicy());
- QualType qual_type(GetQualType());
+ clang::PrintingPolicy printing_policy (m_ast->getPrintingPolicy());
+ clang::QualType qual_type(GetQualType());
printing_policy.SuppressTagKeyword = true;
printing_policy.LangOpts.WChar = true;
- const TypedefType *typedef_type = qual_type->getAs<TypedefType>();
+ const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
if (typedef_type)
{
- const TypedefNameDecl *typedef_decl = typedef_type->getDecl();
+ const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
type_name = typedef_decl->getQualifiedNameAsString();
}
else
@@ -1145,6 +1244,11 @@ ClangASTType::GetTypeName () const
return ConstString(type_name);
}
+ConstString
+ClangASTType::GetDisplayTypeName () const
+{
+ return GetTypeName();
+}
uint32_t
ClangASTType::GetTypeInfo (ClangASTType *pointee_or_element_clang_type) const
@@ -1155,14 +1259,14 @@ ClangASTType::GetTypeInfo (ClangASTType *pointee_or_element_clang_type) const
if (pointee_or_element_clang_type)
pointee_or_element_clang_type->Clear();
- QualType qual_type (GetQualType());
+ clang::QualType qual_type (GetQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Builtin:
{
- const BuiltinType *builtin_type = dyn_cast<BuiltinType>(qual_type->getCanonicalTypeInternal());
+ const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());
uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue;
switch (builtin_type->getKind())
@@ -1226,10 +1330,10 @@ ClangASTType::GetTypeInfo (ClangASTType *pointee_or_element_clang_type) const
case clang::Type::Complex:
{
uint32_t complex_type_flags = eTypeIsBuiltIn | eTypeHasValue | eTypeIsComplex;
- const ComplexType *complex_type = dyn_cast<ComplexType>(qual_type->getCanonicalTypeInternal());
+ const clang::ComplexType *complex_type = llvm::dyn_cast<clang::ComplexType>(qual_type->getCanonicalTypeInternal());
if (complex_type)
{
- QualType complex_element_type (complex_type->getElementType());
+ clang::QualType complex_element_type (complex_type->getElementType());
if (complex_element_type->isIntegerType())
complex_type_flags |= eTypeIsFloat;
else if (complex_element_type->isFloatingType())
@@ -1244,7 +1348,7 @@ ClangASTType::GetTypeInfo (ClangASTType *pointee_or_element_clang_type) const
case clang::Type::IncompleteArray:
case clang::Type::VariableArray:
if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetClangType(m_ast, cast<ArrayType>(qual_type.getTypePtr())->getElementType());
+ pointee_or_element_clang_type->SetClangType(m_ast, llvm::cast<clang::ArrayType>(qual_type.getTypePtr())->getElementType());
return eTypeHasChildren | eTypeIsArray;
case clang::Type::DependentName: return 0;
@@ -1254,13 +1358,13 @@ ClangASTType::GetTypeInfo (ClangASTType *pointee_or_element_clang_type) const
case clang::Type::Enum:
if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetClangType(m_ast, cast<EnumType>(qual_type)->getDecl()->getIntegerType());
+ pointee_or_element_clang_type->SetClangType(m_ast, llvm::cast<clang::EnumType>(qual_type)->getDecl()->getIntegerType());
return eTypeIsEnumeration | eTypeHasValue;
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetTypeInfo (pointee_or_element_clang_type);
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetTypeInfo (pointee_or_element_clang_type);
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).GetTypeInfo (pointee_or_element_clang_type);
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetTypeInfo (pointee_or_element_clang_type);
case clang::Type::FunctionProto: return eTypeIsFuncPrototype | eTypeHasValue;
case clang::Type::FunctionNoProto: return eTypeIsFuncPrototype | eTypeHasValue;
@@ -1269,7 +1373,7 @@ ClangASTType::GetTypeInfo (ClangASTType *pointee_or_element_clang_type) const
case clang::Type::LValueReference:
case clang::Type::RValueReference:
if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetClangType(m_ast, cast<ReferenceType>(qual_type.getTypePtr())->getPointeeType());
+ pointee_or_element_clang_type->SetClangType(m_ast, llvm::cast<clang::ReferenceType>(qual_type.getTypePtr())->getPointeeType());
return eTypeHasChildren | eTypeIsReference | eTypeHasValue;
case clang::Type::MemberPointer: return eTypeIsPointer | eTypeIsMember | eTypeHasValue;
@@ -1298,7 +1402,7 @@ ClangASTType::GetTypeInfo (ClangASTType *pointee_or_element_clang_type) const
case clang::Type::TemplateSpecialization: return eTypeIsTemplate;
case clang::Type::Typedef:
- return eTypeIsTypedef | ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetTypeInfo (pointee_or_element_clang_type);
+ return eTypeIsTypedef | ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetTypeInfo (pointee_or_element_clang_type);
case clang::Type::TypeOfExpr: return 0;
case clang::Type::TypeOf: return 0;
case clang::Type::UnresolvedUsing: return 0;
@@ -1307,7 +1411,7 @@ ClangASTType::GetTypeInfo (ClangASTType *pointee_or_element_clang_type) const
case clang::Type::Vector:
{
uint32_t vector_type_flags = eTypeHasChildren | eTypeIsVector;
- const VectorType *vector_type = dyn_cast<VectorType>(qual_type->getCanonicalTypeInternal());
+ const clang::VectorType *vector_type = llvm::dyn_cast<clang::VectorType>(qual_type->getCanonicalTypeInternal());
if (vector_type)
{
if (vector_type->isIntegerType())
@@ -1331,14 +1435,14 @@ ClangASTType::GetMinimumLanguage ()
return lldb::eLanguageTypeC;
// If the type is a reference, then resolve it to what it refers to first:
- QualType qual_type (GetCanonicalQualType().getNonReferenceType());
+ clang::QualType qual_type (GetCanonicalQualType().getNonReferenceType());
if (qual_type->isAnyPointerType())
{
if (qual_type->isObjCObjectPointerType())
return lldb::eLanguageTypeObjC;
- QualType pointee_type (qual_type->getPointeeType());
- if (pointee_type->getPointeeCXXRecordDecl() != NULL)
+ clang::QualType pointee_type (qual_type->getPointeeType());
+ if (pointee_type->getPointeeCXXRecordDecl() != nullptr)
return lldb::eLanguageTypeC_plus_plus;
if (pointee_type->isObjCObjectOrInterfaceType())
return lldb::eLanguageTypeObjC;
@@ -1358,51 +1462,51 @@ ClangASTType::GetMinimumLanguage ()
default:
break;
case clang::Type::Builtin:
- switch (cast<BuiltinType>(qual_type)->getKind())
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
{
default:
- case BuiltinType::Void:
- case BuiltinType::Bool:
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::WChar_U:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::UShort:
- case BuiltinType::UInt:
- case BuiltinType::ULong:
- case BuiltinType::ULongLong:
- case BuiltinType::UInt128:
- case BuiltinType::Char_S:
- case BuiltinType::SChar:
- case BuiltinType::WChar_S:
- case BuiltinType::Short:
- case BuiltinType::Int:
- case BuiltinType::Long:
- case BuiltinType::LongLong:
- case BuiltinType::Int128:
- case BuiltinType::Float:
- case BuiltinType::Double:
- case BuiltinType::LongDouble:
+ case clang::BuiltinType::Void:
+ case clang::BuiltinType::Bool:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
+ case clang::BuiltinType::UShort:
+ case clang::BuiltinType::UInt:
+ case clang::BuiltinType::ULong:
+ case clang::BuiltinType::ULongLong:
+ case clang::BuiltinType::UInt128:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Short:
+ case clang::BuiltinType::Int:
+ case clang::BuiltinType::Long:
+ case clang::BuiltinType::LongLong:
+ case clang::BuiltinType::Int128:
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::LongDouble:
break;
- case BuiltinType::NullPtr:
+ case clang::BuiltinType::NullPtr:
return eLanguageTypeC_plus_plus;
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ case clang::BuiltinType::ObjCSel:
return eLanguageTypeObjC;
- case BuiltinType::Dependent:
- case BuiltinType::Overload:
- case BuiltinType::BoundMember:
- case BuiltinType::UnknownAny:
+ case clang::BuiltinType::Dependent:
+ case clang::BuiltinType::Overload:
+ case clang::BuiltinType::BoundMember:
+ case clang::BuiltinType::UnknownAny:
break;
}
break;
case clang::Type::Typedef:
- return ClangASTType(m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetMinimumLanguage();
+ return ClangASTType(m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetMinimumLanguage();
}
}
return lldb::eLanguageTypeC;
@@ -1414,7 +1518,7 @@ ClangASTType::GetTypeClass () const
if (!IsValid())
return lldb::eTypeClassInvalid;
- QualType qual_type(GetQualType());
+ clang::QualType qual_type(GetQualType());
switch (qual_type->getTypeClass())
{
@@ -1444,8 +1548,8 @@ ClangASTType::GetTypeClass () const
case clang::Type::ObjCInterface: return lldb::eTypeClassObjCInterface;
case clang::Type::Record:
{
- const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
- const RecordDecl *record_decl = record_type->getDecl();
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
if (record_decl->isUnion())
return lldb::eTypeClassUnion;
else if (record_decl->isStruct())
@@ -1458,9 +1562,9 @@ ClangASTType::GetTypeClass () const
case clang::Type::Typedef: return lldb::eTypeClassTypedef;
case clang::Type::UnresolvedUsing: break;
case clang::Type::Paren:
- return ClangASTType(m_ast, cast<ParenType>(qual_type)->desugar()).GetTypeClass();
+ return ClangASTType(m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetTypeClass();
case clang::Type::Elaborated:
- return ClangASTType(m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetTypeClass();
+ return ClangASTType(m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetTypeClass();
case clang::Type::Attributed: break;
case clang::Type::TemplateTypeParm: break;
@@ -1480,6 +1584,7 @@ ClangASTType::GetTypeClass () const
// pointer type decayed from an array or function type.
case clang::Type::Decayed: break;
+ case clang::Type::Adjusted: break;
}
// We don't know hot to display this type...
return lldb::eTypeClassOther;
@@ -1510,7 +1615,7 @@ ClangASTType::AddConstModifier () const
{
if (m_type)
{
- QualType result(GetQualType());
+ clang::QualType result(GetQualType());
result.addConst();
return ClangASTType (m_ast, result);
}
@@ -1522,7 +1627,7 @@ ClangASTType::AddRestrictModifier () const
{
if (m_type)
{
- QualType result(GetQualType());
+ clang::QualType result(GetQualType());
result.getQualifiers().setRestrict (true);
return ClangASTType (m_ast, result);
}
@@ -1534,7 +1639,7 @@ ClangASTType::AddVolatileModifier () const
{
if (m_type)
{
- QualType result(GetQualType());
+ clang::QualType result(GetQualType());
result.getQualifiers().setVolatile (true);
return ClangASTType (m_ast, result);
}
@@ -1542,16 +1647,22 @@ ClangASTType::AddVolatileModifier () const
}
ClangASTType
-ClangASTType::GetArrayElementType (uint64_t& stride) const
+ClangASTType::GetArrayElementType (uint64_t *stride) const
{
if (IsValid())
{
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
+
+ const clang::Type *array_elem_type = qual_type.getTypePtr()->getArrayElementTypeNoTypeQual();
+
+ if (!array_elem_type)
+ return ClangASTType();
- ClangASTType element_type (m_ast, qual_type.getTypePtr()->getArrayElementTypeNoTypeQual()->getCanonicalTypeUnqualified());
+ ClangASTType element_type (m_ast, array_elem_type->getCanonicalTypeUnqualified());
// TODO: the real stride will be >= this value.. find the real one!
- stride = element_type.GetByteSize();
+ if (stride)
+ *stride = element_type.GetByteSize();
return element_type;
@@ -1567,8 +1678,8 @@ ClangASTType::GetCanonicalType () const
return ClangASTType();
}
-static QualType
-GetFullyUnqualifiedType_Impl (ASTContext *ast, QualType qual_type)
+static clang::QualType
+GetFullyUnqualifiedType_Impl (clang::ASTContext *ast, clang::QualType qual_type)
{
if (qual_type->isPointerType())
qual_type = ast->getPointerType(GetFullyUnqualifiedType_Impl(ast, qual_type->getPointeeType()));
@@ -1594,7 +1705,7 @@ ClangASTType::GetFunctionArgumentCount () const
{
if (IsValid())
{
- const FunctionProtoType* func = dyn_cast<FunctionProtoType>(GetCanonicalQualType());
+ const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(GetCanonicalQualType());
if (func)
return func->getNumParams();
}
@@ -1606,7 +1717,7 @@ ClangASTType::GetFunctionArgumentTypeAtIndex (size_t idx)
{
if (IsValid())
{
- const FunctionProtoType* func = dyn_cast<FunctionProtoType>(GetCanonicalQualType());
+ const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(GetCanonicalQualType());
if (func)
{
const uint32_t num_args = func->getNumParams();
@@ -1622,8 +1733,8 @@ ClangASTType::GetFunctionReturnType () const
{
if (IsValid())
{
- QualType qual_type(GetCanonicalQualType());
- const FunctionProtoType* func = dyn_cast<FunctionProtoType>(qual_type.getTypePtr());
+ clang::QualType qual_type(GetCanonicalQualType());
+ const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
if (func)
return ClangASTType(m_ast, func->getReturnType());
}
@@ -1665,19 +1776,19 @@ ClangASTType::CreateTypedefType (const char *typedef_name,
{
if (IsValid() && typedef_name && typedef_name[0])
{
- QualType qual_type (GetQualType());
- if (decl_ctx == NULL)
+ clang::QualType qual_type (GetQualType());
+ if (decl_ctx == nullptr)
decl_ctx = m_ast->getTranslationUnitDecl();
- TypedefDecl *decl = TypedefDecl::Create (*m_ast,
- decl_ctx,
- SourceLocation(),
- SourceLocation(),
- &m_ast->Idents.get(typedef_name),
- m_ast->getTrivialTypeSourceInfo(qual_type));
+ clang::TypedefDecl *decl = clang::TypedefDecl::Create (*m_ast,
+ decl_ctx,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ &m_ast->Idents.get(typedef_name),
+ m_ast->getTrivialTypeSourceInfo(qual_type));
- decl->setAccess(AS_public); // TODO respect proper access specifier
+ decl->setAccess(clang::AS_public); // TODO respect proper access specifier
- // Get a uniqued QualType for the typedef decl type
+ // Get a uniqued clang::QualType for the typedef decl type
return ClangASTType (m_ast, m_ast->getTypedefType (decl));
}
return ClangASTType();
@@ -1689,7 +1800,7 @@ ClangASTType::GetPointeeType () const
{
if (m_type)
{
- QualType qual_type(GetQualType());
+ clang::QualType qual_type(GetQualType());
return ClangASTType (m_ast, qual_type.getTypePtr()->getPointeeType());
}
return ClangASTType();
@@ -1700,7 +1811,7 @@ ClangASTType::GetPointerType () const
{
if (IsValid())
{
- QualType qual_type (GetQualType());
+ clang::QualType qual_type (GetQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
@@ -1721,7 +1832,7 @@ ClangASTType::GetTypedefedType () const
{
if (IsValid())
{
- const TypedefType *typedef_type = dyn_cast<TypedefType>(GetQualType());
+ const clang::TypedefType *typedef_type = llvm::dyn_cast<clang::TypedefType>(GetQualType());
if (typedef_type)
return ClangASTType (m_ast, typedef_type->getDecl()->getUnderlyingType());
}
@@ -1733,7 +1844,7 @@ ClangASTType::RemoveFastQualifiers () const
{
if (m_type)
{
- QualType qual_type(GetQualType());
+ clang::QualType qual_type(GetQualType());
qual_type.getQualifiers().removeFastQualifiers();
return ClangASTType (m_ast, qual_type);
}
@@ -1761,7 +1872,7 @@ ClangASTType::GetBitSize () const
{
if (GetCompleteType ())
{
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
const uint32_t bit_size = m_ast->getTypeSize (qual_type);
if (bit_size == 0)
{
@@ -1797,7 +1908,7 @@ ClangASTType::GetEncoding (uint64_t &count) const
return lldb::eEncodingInvalid;
count = 1;
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
switch (qual_type->getTypeClass())
{
@@ -1821,42 +1932,42 @@ ClangASTType::GetEncoding (uint64_t &count) const
break;
case clang::Type::Builtin:
- switch (cast<BuiltinType>(qual_type)->getKind())
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
{
default: assert(0 && "Unknown builtin type!");
- case BuiltinType::Void:
+ case clang::BuiltinType::Void:
break;
- case BuiltinType::Bool:
- case BuiltinType::Char_S:
- case BuiltinType::SChar:
- case BuiltinType::WChar_S:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::Short:
- case BuiltinType::Int:
- case BuiltinType::Long:
- case BuiltinType::LongLong:
- case BuiltinType::Int128: return lldb::eEncodingSint;
+ case clang::BuiltinType::Bool:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
+ case clang::BuiltinType::Short:
+ case clang::BuiltinType::Int:
+ case clang::BuiltinType::Long:
+ case clang::BuiltinType::LongLong:
+ case clang::BuiltinType::Int128: return lldb::eEncodingSint;
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::WChar_U:
- case BuiltinType::UShort:
- case BuiltinType::UInt:
- case BuiltinType::ULong:
- case BuiltinType::ULongLong:
- case BuiltinType::UInt128: return lldb::eEncodingUint;
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::UShort:
+ case clang::BuiltinType::UInt:
+ case clang::BuiltinType::ULong:
+ case clang::BuiltinType::ULongLong:
+ case clang::BuiltinType::UInt128: return lldb::eEncodingUint;
- case BuiltinType::Float:
- case BuiltinType::Double:
- case BuiltinType::LongDouble: return lldb::eEncodingIEEE754;
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::LongDouble: return lldb::eEncodingIEEE754;
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCSel: return lldb::eEncodingUint;
+ case clang::BuiltinType::ObjCClass:
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCSel: return lldb::eEncodingUint;
- case BuiltinType::NullPtr: return lldb::eEncodingUint;
+ case clang::BuiltinType::NullPtr: return lldb::eEncodingUint;
}
break;
// All pointer types are represented as unsigned integer encodings.
@@ -1875,7 +1986,7 @@ ClangASTType::GetEncoding (uint64_t &count) const
encoding = lldb::eEncodingIEEE754;
else
{
- const ComplexType *complex_type = qual_type->getAsComplexIntegerType();
+ const clang::ComplexType *complex_type = qual_type->getAsComplexIntegerType();
if (complex_type)
encoding = ClangASTType(m_ast, complex_type->getElementType()).GetEncoding(count);
else
@@ -1889,13 +2000,13 @@ ClangASTType::GetEncoding (uint64_t &count) const
case clang::Type::Record: break;
case clang::Type::Enum: return lldb::eEncodingSint;
case clang::Type::Typedef:
- return ClangASTType(m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetEncoding(count);
+ return ClangASTType(m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetEncoding(count);
case clang::Type::Elaborated:
- return ClangASTType(m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetEncoding(count);
+ return ClangASTType(m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetEncoding(count);
case clang::Type::Paren:
- return ClangASTType(m_ast, cast<ParenType>(qual_type)->desugar()).GetEncoding(count);
+ return ClangASTType(m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetEncoding(count);
case clang::Type::DependentSizedArray:
case clang::Type::DependentSizedExtVector:
@@ -1916,6 +2027,7 @@ ClangASTType::GetEncoding (uint64_t &count) const
case clang::Type::Decltype:
case clang::Type::TemplateSpecialization:
case clang::Type::Atomic:
+ case clang::Type::Adjusted:
break;
// pointer type decayed from an array or function type.
@@ -1932,7 +2044,7 @@ ClangASTType::GetFormat () const
if (!IsValid())
return lldb::eFormatDefault;
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
switch (qual_type->getTypeClass())
{
@@ -1955,54 +2067,54 @@ ClangASTType::GetFormat () const
break;
case clang::Type::Builtin:
- switch (cast<BuiltinType>(qual_type)->getKind())
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
{
//default: assert(0 && "Unknown builtin type!");
- case BuiltinType::UnknownAny:
- case BuiltinType::Void:
- case BuiltinType::BoundMember:
+ case clang::BuiltinType::UnknownAny:
+ case clang::BuiltinType::Void:
+ case clang::BuiltinType::BoundMember:
break;
- case BuiltinType::Bool: return lldb::eFormatBoolean;
- case BuiltinType::Char_S:
- case BuiltinType::SChar:
- case BuiltinType::WChar_S:
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::WChar_U: return lldb::eFormatChar;
- case BuiltinType::Char16: return lldb::eFormatUnicode16;
- case BuiltinType::Char32: return lldb::eFormatUnicode32;
- case BuiltinType::UShort: return lldb::eFormatUnsigned;
- case BuiltinType::Short: return lldb::eFormatDecimal;
- case BuiltinType::UInt: return lldb::eFormatUnsigned;
- case BuiltinType::Int: return lldb::eFormatDecimal;
- case BuiltinType::ULong: return lldb::eFormatUnsigned;
- case BuiltinType::Long: return lldb::eFormatDecimal;
- case BuiltinType::ULongLong: return lldb::eFormatUnsigned;
- case BuiltinType::LongLong: return lldb::eFormatDecimal;
- case BuiltinType::UInt128: return lldb::eFormatUnsigned;
- case BuiltinType::Int128: return lldb::eFormatDecimal;
- case BuiltinType::Float: return lldb::eFormatFloat;
- case BuiltinType::Double: return lldb::eFormatFloat;
- case BuiltinType::LongDouble: return lldb::eFormatFloat;
- case BuiltinType::NullPtr:
- case BuiltinType::Overload:
- case BuiltinType::Dependent:
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
- case BuiltinType::Half:
- case BuiltinType::ARCUnbridgedCast:
- case BuiltinType::PseudoObject:
- case BuiltinType::BuiltinFn:
- case BuiltinType::OCLEvent:
- case BuiltinType::OCLImage1d:
- case BuiltinType::OCLImage1dArray:
- case BuiltinType::OCLImage1dBuffer:
- case BuiltinType::OCLImage2d:
- case BuiltinType::OCLImage2dArray:
- case BuiltinType::OCLImage3d:
- case BuiltinType::OCLSampler:
+ case clang::BuiltinType::Bool: return lldb::eFormatBoolean;
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::WChar_U: return lldb::eFormatChar;
+ case clang::BuiltinType::Char16: return lldb::eFormatUnicode16;
+ case clang::BuiltinType::Char32: return lldb::eFormatUnicode32;
+ case clang::BuiltinType::UShort: return lldb::eFormatUnsigned;
+ case clang::BuiltinType::Short: return lldb::eFormatDecimal;
+ case clang::BuiltinType::UInt: return lldb::eFormatUnsigned;
+ case clang::BuiltinType::Int: return lldb::eFormatDecimal;
+ case clang::BuiltinType::ULong: return lldb::eFormatUnsigned;
+ case clang::BuiltinType::Long: return lldb::eFormatDecimal;
+ case clang::BuiltinType::ULongLong: return lldb::eFormatUnsigned;
+ case clang::BuiltinType::LongLong: return lldb::eFormatDecimal;
+ case clang::BuiltinType::UInt128: return lldb::eFormatUnsigned;
+ case clang::BuiltinType::Int128: return lldb::eFormatDecimal;
+ case clang::BuiltinType::Float: return lldb::eFormatFloat;
+ case clang::BuiltinType::Double: return lldb::eFormatFloat;
+ case clang::BuiltinType::LongDouble: return lldb::eFormatFloat;
+ case clang::BuiltinType::NullPtr:
+ case clang::BuiltinType::Overload:
+ case clang::BuiltinType::Dependent:
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ case clang::BuiltinType::ObjCSel:
+ case clang::BuiltinType::Half:
+ case clang::BuiltinType::ARCUnbridgedCast:
+ case clang::BuiltinType::PseudoObject:
+ case clang::BuiltinType::BuiltinFn:
+ case clang::BuiltinType::OCLEvent:
+ case clang::BuiltinType::OCLImage1d:
+ case clang::BuiltinType::OCLImage1dArray:
+ case clang::BuiltinType::OCLImage1dBuffer:
+ case clang::BuiltinType::OCLImage2d:
+ case clang::BuiltinType::OCLImage2dArray:
+ case clang::BuiltinType::OCLImage3d:
+ case clang::BuiltinType::OCLSampler:
return lldb::eFormatHex;
}
break;
@@ -2023,13 +2135,13 @@ ClangASTType::GetFormat () const
case clang::Type::Record: break;
case clang::Type::Enum: return lldb::eFormatEnum;
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetFormat();
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetFormat();
case clang::Type::Auto:
- return ClangASTType (m_ast, cast<AutoType>(qual_type)->desugar()).GetFormat();
+ return ClangASTType (m_ast, llvm::cast<clang::AutoType>(qual_type)->desugar()).GetFormat();
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<ParenType>(qual_type)->desugar()).GetFormat();
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetFormat();
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetFormat();
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetFormat();
case clang::Type::DependentSizedArray:
case clang::Type::DependentSizedExtVector:
case clang::Type::UnresolvedUsing:
@@ -2048,6 +2160,7 @@ ClangASTType::GetFormat () const
case clang::Type::Decltype:
case clang::Type::TemplateSpecialization:
case clang::Type::Atomic:
+ case clang::Type::Adjusted:
break;
// pointer type decayed from an array or function type.
@@ -2059,7 +2172,7 @@ ClangASTType::GetFormat () const
}
static bool
-ObjCDeclHasIVars (ObjCInterfaceDecl *class_interface_decl, bool check_superclass)
+ObjCDeclHasIVars (clang::ObjCInterfaceDecl *class_interface_decl, bool check_superclass)
{
while (class_interface_decl)
{
@@ -2081,15 +2194,15 @@ ClangASTType::GetNumChildren (bool omit_empty_base_classes) const
return 0;
uint32_t num_children = 0;
- QualType qual_type(GetQualType());
+ clang::QualType qual_type(GetQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Builtin:
- switch (cast<BuiltinType>(qual_type)->getKind())
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
{
- case BuiltinType::ObjCId: // child is Class
- case BuiltinType::ObjCClass: // child is Class
+ case clang::BuiltinType::ObjCId: // child is Class
+ case clang::BuiltinType::ObjCClass: // child is Class
num_children = 1;
break;
@@ -2103,10 +2216,10 @@ ClangASTType::GetNumChildren (bool omit_empty_base_classes) const
case clang::Type::Record:
if (GetCompleteQualType (m_ast, qual_type))
{
- const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
- const RecordDecl *record_decl = record_type->getDecl();
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
assert(record_decl);
- const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
if (cxx_record_decl)
{
if (omit_empty_base_classes)
@@ -2115,12 +2228,12 @@ ClangASTType::GetNumChildren (bool omit_empty_base_classes) const
// base classes contain any fields. This can help
// limit the noise in variable views by not having to
// show base classes that contain no members.
- CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
base_class != base_class_end;
++base_class)
{
- const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+ const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
// Skip empty base classes
if (ClangASTContext::RecordHasFields(base_class_decl) == false)
@@ -2136,7 +2249,7 @@ ClangASTType::GetNumChildren (bool omit_empty_base_classes) const
}
}
- RecordDecl::field_iterator field, field_end;
+ clang::RecordDecl::field_iterator field, field_end;
for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field)
++num_children;
}
@@ -2146,16 +2259,16 @@ ClangASTType::GetNumChildren (bool omit_empty_base_classes) const
case clang::Type::ObjCInterface:
if (GetCompleteQualType (m_ast, qual_type))
{
- const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr());
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
assert (objc_class_type);
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
if (class_interface_decl)
{
- ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
if (superclass_interface_decl)
{
if (omit_empty_base_classes)
@@ -2175,8 +2288,8 @@ ClangASTType::GetNumChildren (bool omit_empty_base_classes) const
case clang::Type::ObjCObjectPointer:
{
- const ObjCObjectPointerType *pointer_type = cast<ObjCObjectPointerType>(qual_type.getTypePtr());
- QualType pointee_type = pointer_type->getPointeeType();
+ const clang::ObjCObjectPointerType *pointer_type = llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr());
+ clang::QualType pointee_type = pointer_type->getPointeeType();
uint32_t num_pointee_children = ClangASTType (m_ast,pointee_type).GetNumChildren (omit_empty_base_classes);
// If this type points to a simple type, then it has 1 child
if (num_pointee_children == 0)
@@ -2188,17 +2301,17 @@ ClangASTType::GetNumChildren (bool omit_empty_base_classes) const
case clang::Type::Vector:
case clang::Type::ExtVector:
- num_children = cast<VectorType>(qual_type.getTypePtr())->getNumElements();
+ num_children = llvm::cast<clang::VectorType>(qual_type.getTypePtr())->getNumElements();
break;
case clang::Type::ConstantArray:
- num_children = cast<ConstantArrayType>(qual_type.getTypePtr())->getSize().getLimitedValue();
+ num_children = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr())->getSize().getLimitedValue();
break;
case clang::Type::Pointer:
{
- const PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
- QualType pointee_type (pointer_type->getPointeeType());
+ const clang::PointerType *pointer_type = llvm::cast<clang::PointerType>(qual_type.getTypePtr());
+ clang::QualType pointee_type (pointer_type->getPointeeType());
uint32_t num_pointee_children = ClangASTType (m_ast,pointee_type).GetNumChildren (omit_empty_base_classes);
if (num_pointee_children == 0)
{
@@ -2214,8 +2327,8 @@ ClangASTType::GetNumChildren (bool omit_empty_base_classes) const
case clang::Type::LValueReference:
case clang::Type::RValueReference:
{
- const ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr());
- QualType pointee_type = reference_type->getPointeeType();
+ const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+ clang::QualType pointee_type = reference_type->getPointeeType();
uint32_t num_pointee_children = ClangASTType (m_ast, pointee_type).GetNumChildren (omit_empty_base_classes);
// If this type points to a simple type, then it has 1 child
if (num_pointee_children == 0)
@@ -2227,15 +2340,15 @@ ClangASTType::GetNumChildren (bool omit_empty_base_classes) const
case clang::Type::Typedef:
- num_children = ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumChildren (omit_empty_base_classes);
+ num_children = ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumChildren (omit_empty_base_classes);
break;
case clang::Type::Elaborated:
- num_children = ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetNumChildren (omit_empty_base_classes);
+ num_children = ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumChildren (omit_empty_base_classes);
break;
case clang::Type::Paren:
- num_children = ClangASTType (m_ast, cast<ParenType>(qual_type)->desugar()).GetNumChildren (omit_empty_base_classes);
+ num_children = ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumChildren (omit_empty_base_classes);
break;
default:
break;
@@ -2248,11 +2361,11 @@ ClangASTType::GetBasicTypeEnumeration () const
{
if (IsValid())
{
- QualType qual_type(GetQualType());
+ clang::QualType qual_type(GetQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
if (type_class == clang::Type::Builtin)
{
- switch (cast<clang::BuiltinType>(qual_type)->getKind())
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
{
case clang::BuiltinType::Void: return eBasicTypeVoid;
case clang::BuiltinType::Bool: return eBasicTypeBool;
@@ -2316,14 +2429,14 @@ ClangASTType::GetNumDirectBaseClasses () const
return 0;
uint32_t count = 0;
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Record:
if (GetCompleteType())
{
- const CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
if (cxx_record_decl)
count = cxx_record_decl->getNumBases();
}
@@ -2336,10 +2449,10 @@ ClangASTType::GetNumDirectBaseClasses () const
case clang::Type::ObjCObject:
if (GetCompleteType())
{
- const ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
+ const clang::ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
if (class_interface_decl && class_interface_decl->getSuperClass())
count = 1;
@@ -2349,10 +2462,10 @@ ClangASTType::GetNumDirectBaseClasses () const
case clang::Type::ObjCInterface:
if (GetCompleteType())
{
- const ObjCInterfaceType *objc_interface_type = qual_type->getAs<ObjCInterfaceType>();
+ const clang::ObjCInterfaceType *objc_interface_type = qual_type->getAs<clang::ObjCInterfaceType>();
if (objc_interface_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface();
if (class_interface_decl && class_interface_decl->getSuperClass())
count = 1;
@@ -2362,15 +2475,15 @@ ClangASTType::GetNumDirectBaseClasses () const
case clang::Type::Typedef:
- count = ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumDirectBaseClasses ();
+ count = ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumDirectBaseClasses ();
break;
case clang::Type::Elaborated:
- count = ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetNumDirectBaseClasses ();
+ count = ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumDirectBaseClasses ();
break;
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).GetNumDirectBaseClasses ();
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumDirectBaseClasses ();
default:
break;
@@ -2385,29 +2498,29 @@ ClangASTType::GetNumVirtualBaseClasses () const
return 0;
uint32_t count = 0;
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Record:
if (GetCompleteType())
{
- const CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
if (cxx_record_decl)
count = cxx_record_decl->getNumVBases();
}
break;
case clang::Type::Typedef:
- count = ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumVirtualBaseClasses();
+ count = ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumVirtualBaseClasses();
break;
case clang::Type::Elaborated:
- count = ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetNumVirtualBaseClasses();
+ count = ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumVirtualBaseClasses();
break;
case clang::Type::Paren:
- count = ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).GetNumVirtualBaseClasses();
+ count = ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumVirtualBaseClasses();
break;
default:
@@ -2423,21 +2536,21 @@ ClangASTType::GetNumFields () const
return 0;
uint32_t count = 0;
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Record:
if (GetCompleteType())
{
- const RecordType *record_type = dyn_cast<RecordType>(qual_type.getTypePtr());
+ const clang::RecordType *record_type = llvm::dyn_cast<clang::RecordType>(qual_type.getTypePtr());
if (record_type)
{
- RecordDecl *record_decl = record_type->getDecl();
+ clang::RecordDecl *record_decl = record_type->getDecl();
if (record_decl)
{
uint32_t field_idx = 0;
- RecordDecl::field_iterator field, field_end;
+ clang::RecordDecl::field_iterator field, field_end;
for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field)
++field_idx;
count = field_idx;
@@ -2447,24 +2560,24 @@ ClangASTType::GetNumFields () const
break;
case clang::Type::Typedef:
- count = ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumFields();
+ count = ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumFields();
break;
case clang::Type::Elaborated:
- count = ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetNumFields();
+ count = ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumFields();
break;
case clang::Type::Paren:
- count = ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).GetNumFields();
+ count = ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumFields();
break;
case clang::Type::ObjCObjectPointer:
if (GetCompleteType())
{
- const ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
+ const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
if (class_interface_decl)
count = class_interface_decl->ivar_size();
@@ -2476,10 +2589,10 @@ ClangASTType::GetNumFields () const
case clang::Type::ObjCInterface:
if (GetCompleteType())
{
- const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr());
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
if (class_interface_decl)
count = class_interface_decl->ivar_size();
@@ -2499,18 +2612,18 @@ ClangASTType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) c
if (!IsValid())
return ClangASTType();
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Record:
if (GetCompleteType())
{
- const CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
if (cxx_record_decl)
{
uint32_t curr_idx = 0;
- CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
base_class != base_class_end;
++base_class, ++curr_idx)
@@ -2519,8 +2632,8 @@ ClangASTType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) c
{
if (bit_offset_ptr)
{
- const ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(cxx_record_decl);
- const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+ const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(cxx_record_decl);
+ const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
if (base_class->isVirtual())
*bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
else
@@ -2539,14 +2652,14 @@ ClangASTType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) c
case clang::Type::ObjCObject:
if (idx == 0 && GetCompleteType())
{
- const ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
+ const clang::ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
if (class_interface_decl)
{
- ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
if (superclass_interface_decl)
{
if (bit_offset_ptr)
@@ -2560,14 +2673,14 @@ ClangASTType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) c
case clang::Type::ObjCInterface:
if (idx == 0 && GetCompleteType())
{
- const ObjCObjectType *objc_interface_type = qual_type->getAs<ObjCInterfaceType>();
+ const clang::ObjCObjectType *objc_interface_type = qual_type->getAs<clang::ObjCInterfaceType>();
if (objc_interface_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface();
if (class_interface_decl)
{
- ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
if (superclass_interface_decl)
{
if (bit_offset_ptr)
@@ -2581,13 +2694,13 @@ ClangASTType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) c
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetDirectBaseClassAtIndex (idx, bit_offset_ptr);
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetDirectBaseClassAtIndex (idx, bit_offset_ptr);
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetDirectBaseClassAtIndex (idx, bit_offset_ptr);
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetDirectBaseClassAtIndex (idx, bit_offset_ptr);
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).GetDirectBaseClassAtIndex (idx, bit_offset_ptr);
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetDirectBaseClassAtIndex (idx, bit_offset_ptr);
default:
break;
@@ -2601,18 +2714,18 @@ ClangASTType::GetVirtualBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr)
if (!IsValid())
return ClangASTType();
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Record:
if (GetCompleteType())
{
- const CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
if (cxx_record_decl)
{
uint32_t curr_idx = 0;
- CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
for (base_class = cxx_record_decl->vbases_begin(), base_class_end = cxx_record_decl->vbases_end();
base_class != base_class_end;
++base_class, ++curr_idx)
@@ -2621,8 +2734,8 @@ ClangASTType::GetVirtualBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr)
{
if (bit_offset_ptr)
{
- const ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(cxx_record_decl);
- const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+ const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(cxx_record_decl);
+ const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
*bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
}
@@ -2634,13 +2747,13 @@ ClangASTType::GetVirtualBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr)
break;
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetVirtualBaseClassAtIndex (idx, bit_offset_ptr);
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetVirtualBaseClassAtIndex (idx, bit_offset_ptr);
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetVirtualBaseClassAtIndex (idx, bit_offset_ptr);
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetVirtualBaseClassAtIndex (idx, bit_offset_ptr);
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).GetVirtualBaseClassAtIndex (idx, bit_offset_ptr);
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetVirtualBaseClassAtIndex (idx, bit_offset_ptr);
default:
break;
@@ -2650,7 +2763,7 @@ ClangASTType::GetVirtualBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr)
static clang_type_t
GetObjCFieldAtIndex (clang::ASTContext *ast,
- ObjCInterfaceDecl *class_interface_decl,
+ clang::ObjCInterfaceDecl *class_interface_decl,
size_t idx,
std::string& name,
uint64_t *bit_offset_ptr,
@@ -2661,22 +2774,22 @@ GetObjCFieldAtIndex (clang::ASTContext *ast,
{
if (idx < (class_interface_decl->ivar_size()))
{
- ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
+ clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
uint32_t ivar_idx = 0;
for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++ivar_idx)
{
if (ivar_idx == idx)
{
- const ObjCIvarDecl* ivar_decl = *ivar_pos;
+ const clang::ObjCIvarDecl* ivar_decl = *ivar_pos;
- QualType ivar_qual_type(ivar_decl->getType());
+ clang::QualType ivar_qual_type(ivar_decl->getType());
name.assign(ivar_decl->getNameAsString());
if (bit_offset_ptr)
{
- const ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl);
+ const clang::ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl);
*bit_offset_ptr = interface_layout.getFieldOffset (ivar_idx);
}
@@ -2688,7 +2801,7 @@ GetObjCFieldAtIndex (clang::ASTContext *ast,
if (is_bitfield && ast)
{
- Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth();
+ clang::Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth();
llvm::APSInt bitfield_apsint;
if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *ast))
{
@@ -2704,7 +2817,7 @@ GetObjCFieldAtIndex (clang::ASTContext *ast,
}
}
}
- return NULL;
+ return nullptr;
}
ClangASTType
@@ -2717,17 +2830,17 @@ ClangASTType::GetFieldAtIndex (size_t idx,
if (!IsValid())
return ClangASTType();
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Record:
if (GetCompleteType())
{
- const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
- const RecordDecl *record_decl = record_type->getDecl();
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
uint32_t field_idx = 0;
- RecordDecl::field_iterator field, field_end;
+ clang::RecordDecl::field_iterator field, field_end;
for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx)
{
if (idx == field_idx)
@@ -2740,7 +2853,7 @@ ClangASTType::GetFieldAtIndex (size_t idx,
// alignment (field_type_info.second) from the AST context.
if (bit_offset_ptr)
{
- const ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(record_decl);
+ const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(record_decl);
*bit_offset_ptr = record_layout.getFieldOffset (field_idx);
}
@@ -2752,7 +2865,7 @@ ClangASTType::GetFieldAtIndex (size_t idx,
if (is_bitfield)
{
- Expr *bitfield_bit_size_expr = field->getBitWidth();
+ clang::Expr *bitfield_bit_size_expr = field->getBitWidth();
llvm::APSInt bitfield_apsint;
if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *m_ast))
{
@@ -2772,10 +2885,10 @@ ClangASTType::GetFieldAtIndex (size_t idx,
case clang::Type::ObjCObjectPointer:
if (GetCompleteType())
{
- const ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
+ const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
return ClangASTType (m_ast, GetObjCFieldAtIndex(m_ast, class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr));
}
}
@@ -2785,11 +2898,11 @@ ClangASTType::GetFieldAtIndex (size_t idx,
case clang::Type::ObjCInterface:
if (GetCompleteType())
{
- const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr());
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
assert (objc_class_type);
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
return ClangASTType (m_ast, GetObjCFieldAtIndex(m_ast, class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr));
}
}
@@ -2797,7 +2910,7 @@ ClangASTType::GetFieldAtIndex (size_t idx,
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).
GetFieldAtIndex (idx,
name,
bit_offset_ptr,
@@ -2805,7 +2918,7 @@ ClangASTType::GetFieldAtIndex (size_t idx,
is_bitfield_ptr);
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).
GetFieldAtIndex (idx,
name,
bit_offset_ptr,
@@ -2813,7 +2926,7 @@ ClangASTType::GetFieldAtIndex (size_t idx,
is_bitfield_ptr);
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).
GetFieldAtIndex (idx,
name,
bit_offset_ptr,
@@ -2859,12 +2972,12 @@ ClangASTType::GetNumPointeeChildren () const
if (!IsValid())
return 0;
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Builtin:
- switch (cast<clang::BuiltinType>(qual_type)->getKind())
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
{
case clang::BuiltinType::UnknownAny:
case clang::BuiltinType::Void:
@@ -2930,9 +3043,9 @@ ClangASTType::GetNumPointeeChildren () const
case clang::Type::FunctionProto: return 0; // When we function pointers, they have no children...
case clang::Type::FunctionNoProto: return 0; // When we function pointers, they have no children...
case clang::Type::UnresolvedUsing: return 0;
- case clang::Type::Paren: return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).GetNumPointeeChildren ();
- case clang::Type::Typedef: return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumPointeeChildren ();
- case clang::Type::Elaborated: return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetNumPointeeChildren ();
+ case clang::Type::Paren: return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumPointeeChildren ();
+ case clang::Type::Typedef: return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumPointeeChildren ();
+ case clang::Type::Elaborated: return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumPointeeChildren ();
case clang::Type::TypeOfExpr: return 0;
case clang::Type::TypeOf: return 0;
case clang::Type::Decltype: return 0;
@@ -2956,7 +3069,6 @@ ClangASTType::GetNumPointeeChildren () const
ClangASTType
ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
- const char *parent_name,
size_t idx,
bool transparent_pointers,
bool omit_empty_base_classes,
@@ -2967,12 +3079,13 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
uint32_t &child_bitfield_bit_size,
uint32_t &child_bitfield_bit_offset,
bool &child_is_base_class,
- bool &child_is_deref_of_parent) const
+ bool &child_is_deref_of_parent,
+ ValueObject *valobj) const
{
if (!IsValid())
return ClangASTType();
- QualType parent_qual_type(GetCanonicalQualType());
+ clang::QualType parent_qual_type(GetCanonicalQualType());
const clang::Type::TypeClass parent_type_class = parent_qual_type->getTypeClass();
child_bitfield_bit_size = 0;
child_bitfield_bit_offset = 0;
@@ -2985,7 +3098,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
case clang::Type::Builtin:
if (idx_is_valid)
{
- switch (cast<clang::BuiltinType>(parent_qual_type)->getKind())
+ switch (llvm::cast<clang::BuiltinType>(parent_qual_type)->getKind())
{
case clang::BuiltinType::ObjCId:
case clang::BuiltinType::ObjCClass:
@@ -3002,39 +3115,106 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
case clang::Type::Record:
if (idx_is_valid && GetCompleteType())
{
- const RecordType *record_type = cast<RecordType>(parent_qual_type.getTypePtr());
- const RecordDecl *record_decl = record_type->getDecl();
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(parent_qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
assert(record_decl);
- const ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(record_decl);
+ const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(record_decl);
uint32_t child_idx = 0;
- const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
if (cxx_record_decl)
{
// We might have base classes to print out first
- CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
base_class != base_class_end;
++base_class)
{
- const CXXRecordDecl *base_class_decl = NULL;
+ const clang::CXXRecordDecl *base_class_decl = nullptr;
// Skip empty base classes
if (omit_empty_base_classes)
{
- base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+ base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
if (ClangASTContext::RecordHasFields(base_class_decl) == false)
continue;
}
if (idx == child_idx)
{
- if (base_class_decl == NULL)
- base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+ if (base_class_decl == nullptr)
+ base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
if (base_class->isVirtual())
- bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
+ {
+ bool handled = false;
+ if (valobj)
+ {
+ Error err;
+ AddressType addr_type = eAddressTypeInvalid;
+ lldb::addr_t vtable_ptr_addr = valobj->GetCPPVTableAddress(addr_type);
+
+ if (vtable_ptr_addr != LLDB_INVALID_ADDRESS && addr_type == eAddressTypeLoad)
+ {
+
+ ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process)
+ {
+ clang::VTableContextBase *vtable_ctx = m_ast->getVTableContext();
+ if (vtable_ctx)
+ {
+ if (vtable_ctx->isMicrosoft())
+ {
+ clang::MicrosoftVTableContext *msoft_vtable_ctx = static_cast<clang::MicrosoftVTableContext *>(vtable_ctx);
+
+ if (vtable_ptr_addr)
+ {
+ const lldb::addr_t vbtable_ptr_addr = vtable_ptr_addr + record_layout.getVBPtrOffset().getQuantity();
+
+ const lldb::addr_t vbtable_ptr = process->ReadPointerFromMemory(vbtable_ptr_addr, err);
+ if (vbtable_ptr != LLDB_INVALID_ADDRESS)
+ {
+ // Get the index into the virtual base table. The index is the index in uint32_t from vbtable_ptr
+ const unsigned vbtable_index = msoft_vtable_ctx->getVBTableIndex(cxx_record_decl, base_class_decl);
+ const lldb::addr_t base_offset_addr = vbtable_ptr + vbtable_index * 4;
+ const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err);
+ if (base_offset != UINT32_MAX)
+ {
+ handled = true;
+ bit_offset = base_offset * 8;
+ }
+ }
+ }
+ }
+ else
+ {
+ clang::ItaniumVTableContext *itanium_vtable_ctx = static_cast<clang::ItaniumVTableContext *>(vtable_ctx);
+ if (vtable_ptr_addr)
+ {
+ const lldb::addr_t vtable_ptr = process->ReadPointerFromMemory(vtable_ptr_addr, err);
+ if (vtable_ptr != LLDB_INVALID_ADDRESS)
+ {
+ clang::CharUnits base_offset_offset = itanium_vtable_ctx->getVirtualBaseOffsetOffset(cxx_record_decl, base_class_decl);
+ const lldb::addr_t base_offset_addr = vtable_ptr + base_offset_offset.getQuantity();
+ const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err);
+ if (base_offset != UINT32_MAX)
+ {
+ handled = true;
+ bit_offset = base_offset * 8;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+ if (!handled)
+ bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
+ }
else
bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8;
@@ -3057,7 +3237,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
}
// Make sure index is in range...
uint32_t field_idx = 0;
- RecordDecl::field_iterator field, field_end;
+ clang::RecordDecl::field_iterator field, field_end;
for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx)
{
if (idx == child_idx)
@@ -3088,18 +3268,18 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
case clang::Type::ObjCInterface:
if (idx_is_valid && GetCompleteType())
{
- const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(parent_qual_type.getTypePtr());
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(parent_qual_type.getTypePtr());
assert (objc_class_type);
if (objc_class_type)
{
uint32_t child_idx = 0;
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
if (class_interface_decl)
{
- const ASTRecordLayout &interface_layout = m_ast->getASTObjCInterfaceLayout(class_interface_decl);
- ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+ const clang::ASTRecordLayout &interface_layout = m_ast->getASTObjCInterfaceLayout(class_interface_decl);
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
if (superclass_interface_decl)
{
if (omit_empty_base_classes)
@@ -3109,14 +3289,14 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
{
if (idx == 0)
{
- QualType ivar_qual_type(m_ast->getObjCInterfaceType(superclass_interface_decl));
+ clang::QualType ivar_qual_type(m_ast->getObjCInterfaceType(superclass_interface_decl));
child_name.assign(superclass_interface_decl->getNameAsString().c_str());
- std::pair<uint64_t, unsigned> ivar_type_info = m_ast->getTypeInfo(ivar_qual_type.getTypePtr());
+ clang::TypeInfo ivar_type_info = m_ast->getTypeInfo(ivar_qual_type.getTypePtr());
- child_byte_size = ivar_type_info.first / 8;
+ child_byte_size = ivar_type_info.Width / 8;
child_byte_offset = 0;
child_is_base_class = true;
@@ -3134,21 +3314,21 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
if (idx < (child_idx + class_interface_decl->ivar_size()))
{
- ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
+ clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos)
{
if (child_idx == idx)
{
- ObjCIvarDecl* ivar_decl = *ivar_pos;
+ clang::ObjCIvarDecl* ivar_decl = *ivar_pos;
- QualType ivar_qual_type(ivar_decl->getType());
+ clang::QualType ivar_qual_type(ivar_decl->getType());
child_name.assign(ivar_decl->getNameAsString().c_str());
- std::pair<uint64_t, unsigned> ivar_type_info = m_ast->getTypeInfo(ivar_qual_type.getTypePtr());
+ clang::TypeInfo ivar_type_info = m_ast->getTypeInfo(ivar_qual_type.getTypePtr());
- child_byte_size = ivar_type_info.first / 8;
+ child_byte_size = ivar_type_info.Width / 8;
// Figure out the field offset within the current struct/union/class type
// For ObjC objects, we can't trust the bit offset we get from the Clang AST, since
@@ -3156,13 +3336,13 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
// the changing size of base classes that are newer than this class.
// So if we have a process around that we can ask about this object, do so.
child_byte_offset = LLDB_INVALID_IVAR_OFFSET;
- Process *process = NULL;
+ Process *process = nullptr;
if (exe_ctx)
process = exe_ctx->GetProcessPtr();
if (process)
{
ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
- if (objc_runtime != NULL)
+ if (objc_runtime != nullptr)
{
ClangASTType parent_ast_type (m_ast, parent_qual_type);
child_byte_offset = objc_runtime->GetByteOffsetForIvar (parent_ast_type, ivar_decl->getNameAsString().c_str());
@@ -3172,7 +3352,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
// Setting this to UINT32_MAX to make sure we don't compute it twice...
bit_offset = UINT32_MAX;
- if (child_byte_offset == LLDB_INVALID_IVAR_OFFSET)
+ if (child_byte_offset == static_cast<int32_t>(LLDB_INVALID_IVAR_OFFSET))
{
bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx);
child_byte_offset = bit_offset / 8;
@@ -3209,7 +3389,6 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
child_is_deref_of_parent = false;
bool tmp_child_is_deref_of_parent = false;
return pointee_clang_type.GetChildClangTypeAtIndex (exe_ctx,
- parent_name,
idx,
transparent_pointers,
omit_empty_base_classes,
@@ -3220,11 +3399,13 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
child_bitfield_bit_size,
child_bitfield_bit_offset,
child_is_base_class,
- tmp_child_is_deref_of_parent);
+ tmp_child_is_deref_of_parent,
+ valobj);
}
else
{
child_is_deref_of_parent = true;
+ const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL;
if (parent_name)
{
child_name.assign(1, '*');
@@ -3246,7 +3427,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
case clang::Type::ExtVector:
if (idx_is_valid)
{
- const VectorType *array = cast<VectorType>(parent_qual_type.getTypePtr());
+ const clang::VectorType *array = llvm::cast<clang::VectorType>(parent_qual_type.getTypePtr());
if (array)
{
ClangASTType element_type (m_ast, array->getElementType());
@@ -3267,7 +3448,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
case clang::Type::IncompleteArray:
if (ignore_array_bounds || idx_is_valid)
{
- const ArrayType *array = cast<ArrayType>(parent_qual_type.getTypePtr());
+ const clang::ArrayType *array = llvm::cast<clang::ArrayType>(parent_qual_type.getTypePtr());
if (array)
{
ClangASTType element_type (m_ast, array->getElementType());
@@ -3299,7 +3480,6 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
child_is_deref_of_parent = false;
bool tmp_child_is_deref_of_parent = false;
return pointee_clang_type.GetChildClangTypeAtIndex (exe_ctx,
- parent_name,
idx,
transparent_pointers,
omit_empty_base_classes,
@@ -3310,12 +3490,14 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
child_bitfield_bit_size,
child_bitfield_bit_offset,
child_is_base_class,
- tmp_child_is_deref_of_parent);
+ tmp_child_is_deref_of_parent,
+ valobj);
}
else
{
child_is_deref_of_parent = true;
+ const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL;
if (parent_name)
{
child_name.assign(1, '*');
@@ -3337,14 +3519,13 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
case clang::Type::RValueReference:
if (idx_is_valid)
{
- const ReferenceType *reference_type = cast<ReferenceType>(parent_qual_type.getTypePtr());
+ const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr());
ClangASTType pointee_clang_type (m_ast, reference_type->getPointeeType());
if (transparent_pointers && pointee_clang_type.IsAggregateType ())
{
child_is_deref_of_parent = false;
bool tmp_child_is_deref_of_parent = false;
return pointee_clang_type.GetChildClangTypeAtIndex (exe_ctx,
- parent_name,
idx,
transparent_pointers,
omit_empty_base_classes,
@@ -3355,10 +3536,12 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
child_bitfield_bit_size,
child_bitfield_bit_offset,
child_is_base_class,
- tmp_child_is_deref_of_parent);
+ tmp_child_is_deref_of_parent,
+ valobj);
}
else
{
+ const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL;
if (parent_name)
{
child_name.assign(1, '&');
@@ -3378,9 +3561,8 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
case clang::Type::Typedef:
{
- ClangASTType typedefed_clang_type (m_ast, cast<TypedefType>(parent_qual_type)->getDecl()->getUnderlyingType());
+ ClangASTType typedefed_clang_type (m_ast, llvm::cast<clang::TypedefType>(parent_qual_type)->getDecl()->getUnderlyingType());
return typedefed_clang_type.GetChildClangTypeAtIndex (exe_ctx,
- parent_name,
idx,
transparent_pointers,
omit_empty_base_classes,
@@ -3391,15 +3573,15 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
child_bitfield_bit_size,
child_bitfield_bit_offset,
child_is_base_class,
- child_is_deref_of_parent);
+ child_is_deref_of_parent,
+ valobj);
}
break;
case clang::Type::Elaborated:
{
- ClangASTType elaborated_clang_type (m_ast, cast<ElaboratedType>(parent_qual_type)->getNamedType());
+ ClangASTType elaborated_clang_type (m_ast, llvm::cast<clang::ElaboratedType>(parent_qual_type)->getNamedType());
return elaborated_clang_type.GetChildClangTypeAtIndex (exe_ctx,
- parent_name,
idx,
transparent_pointers,
omit_empty_base_classes,
@@ -3410,14 +3592,14 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
child_bitfield_bit_size,
child_bitfield_bit_offset,
child_is_base_class,
- child_is_deref_of_parent);
+ child_is_deref_of_parent,
+ valobj);
}
case clang::Type::Paren:
{
ClangASTType paren_clang_type (m_ast, llvm::cast<clang::ParenType>(parent_qual_type)->desugar());
return paren_clang_type.GetChildClangTypeAtIndex (exe_ctx,
- parent_name,
idx,
transparent_pointers,
omit_empty_base_classes,
@@ -3428,7 +3610,8 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
child_bitfield_bit_size,
child_bitfield_bit_offset,
child_is_base_class,
- child_is_deref_of_parent);
+ child_is_deref_of_parent,
+ valobj);
}
@@ -3439,7 +3622,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
}
static inline bool
-BaseSpecifierIsEmpty (const CXXBaseSpecifier *b)
+BaseSpecifierIsEmpty (const clang::CXXBaseSpecifier *b)
{
return ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl()) == false;
}
@@ -3447,22 +3630,22 @@ BaseSpecifierIsEmpty (const CXXBaseSpecifier *b)
static uint32_t
GetIndexForRecordBase
(
- const RecordDecl *record_decl,
- const CXXBaseSpecifier *base_spec,
+ const clang::RecordDecl *record_decl,
+ const clang::CXXBaseSpecifier *base_spec,
bool omit_empty_base_classes
)
{
uint32_t child_idx = 0;
- const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
// const char *super_name = record_decl->getNameAsCString();
- // const char *base_name = base_spec->getType()->getAs<RecordType>()->getDecl()->getNameAsCString();
+ // const char *base_name = base_spec->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString();
// printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name);
//
if (cxx_record_decl)
{
- CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
base_class != base_class_end;
++base_class)
@@ -3475,7 +3658,7 @@ GetIndexForRecordBase
// printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n", super_name, base_name,
// child_idx,
- // base_class->getType()->getAs<RecordType>()->getDecl()->getNameAsCString());
+ // base_class->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString());
//
//
if (base_class == base_spec)
@@ -3489,14 +3672,14 @@ GetIndexForRecordBase
static uint32_t
-GetIndexForRecordChild (const RecordDecl *record_decl,
- NamedDecl *canonical_decl,
+GetIndexForRecordChild (const clang::RecordDecl *record_decl,
+ clang::NamedDecl *canonical_decl,
bool omit_empty_base_classes)
{
- uint32_t child_idx = ClangASTContext::GetNumBaseClasses (dyn_cast<CXXRecordDecl>(record_decl),
+ uint32_t child_idx = ClangASTContext::GetNumBaseClasses (llvm::dyn_cast<clang::CXXRecordDecl>(record_decl),
omit_empty_base_classes);
- RecordDecl::field_iterator field, field_end;
+ clang::RecordDecl::field_iterator field, field_end;
for (field = record_decl->field_begin(), field_end = record_decl->field_end();
field != field_end;
++field, ++child_idx)
@@ -3549,24 +3732,24 @@ ClangASTType::GetIndexOfChildMemberWithName (const char *name,
{
if (IsValid() && name && name[0])
{
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Record:
if (GetCompleteType ())
{
- const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
- const RecordDecl *record_decl = record_type->getDecl();
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
assert(record_decl);
uint32_t child_idx = 0;
- const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
// Try and find a field that matches NAME
- RecordDecl::field_iterator field, field_end;
- StringRef name_sref(name);
+ clang::RecordDecl::field_iterator field, field_end;
+ llvm::StringRef name_sref(name);
for (field = record_decl->field_begin(), field_end = record_decl->field_end();
field != field_end;
++field, ++child_idx)
@@ -3591,27 +3774,27 @@ ClangASTType::GetIndexOfChildMemberWithName (const char *name,
if (cxx_record_decl)
{
- const RecordDecl *parent_record_decl = cxx_record_decl;
+ const clang::RecordDecl *parent_record_decl = cxx_record_decl;
//printf ("parent = %s\n", parent_record_decl->getNameAsCString());
//const Decl *root_cdecl = cxx_record_decl->getCanonicalDecl();
// Didn't find things easily, lets let clang do its thang...
- IdentifierInfo & ident_ref = m_ast->Idents.get(name_sref);
- DeclarationName decl_name(&ident_ref);
+ clang::IdentifierInfo & ident_ref = m_ast->Idents.get(name_sref);
+ clang::DeclarationName decl_name(&ident_ref);
- CXXBasePaths paths;
- if (cxx_record_decl->lookupInBases(CXXRecordDecl::FindOrdinaryMember,
+ clang::CXXBasePaths paths;
+ if (cxx_record_decl->lookupInBases(clang::CXXRecordDecl::FindOrdinaryMember,
decl_name.getAsOpaquePtr(),
paths))
{
- CXXBasePaths::const_paths_iterator path, path_end = paths.end();
+ clang::CXXBasePaths::const_paths_iterator path, path_end = paths.end();
for (path = paths.begin(); path != path_end; ++path)
{
const size_t num_path_elements = path->size();
for (size_t e=0; e<num_path_elements; ++e)
{
- CXXBasePathElement elem = (*path)[e];
+ clang::CXXBasePathElement elem = (*path)[e];
child_idx = GetIndexForRecordBase (parent_record_decl, elem.Base, omit_empty_base_classes);
if (child_idx == UINT32_MAX)
@@ -3622,10 +3805,10 @@ ClangASTType::GetIndexOfChildMemberWithName (const char *name,
else
{
child_indexes.push_back (child_idx);
- parent_record_decl = cast<RecordDecl>(elem.Base->getType()->getAs<RecordType>()->getDecl());
+ parent_record_decl = llvm::cast<clang::RecordDecl>(elem.Base->getType()->getAs<clang::RecordType>()->getDecl());
}
}
- for (NamedDecl *path_decl : path->Decls)
+ for (clang::NamedDecl *path_decl : path->Decls)
{
child_idx = GetIndexForRecordChild (parent_record_decl, path_decl, omit_empty_base_classes);
if (child_idx == UINT32_MAX)
@@ -3650,22 +3833,22 @@ ClangASTType::GetIndexOfChildMemberWithName (const char *name,
case clang::Type::ObjCInterface:
if (GetCompleteType ())
{
- StringRef name_sref(name);
- const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr());
+ llvm::StringRef name_sref(name);
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
assert (objc_class_type);
if (objc_class_type)
{
uint32_t child_idx = 0;
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
if (class_interface_decl)
{
- ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
- ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+ clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx)
{
- const ObjCIvarDecl* ivar_decl = *ivar_pos;
+ const clang::ObjCIvarDecl* ivar_decl = *ivar_pos;
if (ivar_decl->getName().equals (name_sref))
{
@@ -3707,7 +3890,7 @@ ClangASTType::GetIndexOfChildMemberWithName (const char *name,
case clang::Type::ObjCObjectPointer:
{
- ClangASTType objc_object_clang_type (m_ast, cast<ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType());
+ ClangASTType objc_object_clang_type (m_ast, llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType());
return objc_object_clang_type.GetIndexOfChildMemberWithName (name,
omit_empty_base_classes,
child_indexes);
@@ -3717,7 +3900,7 @@ ClangASTType::GetIndexOfChildMemberWithName (const char *name,
case clang::Type::ConstantArray:
{
- // const ConstantArrayType *array = cast<ConstantArrayType>(parent_qual_type.getTypePtr());
+ // const clang::ConstantArrayType *array = llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr());
// const uint64_t element_count = array->getSize().getLimitedValue();
//
// if (idx < element_count)
@@ -3738,8 +3921,8 @@ ClangASTType::GetIndexOfChildMemberWithName (const char *name,
// case clang::Type::MemberPointerType:
// {
- // MemberPointerType *mem_ptr_type = cast<MemberPointerType>(qual_type.getTypePtr());
- // QualType pointee_type = mem_ptr_type->getPointeeType();
+ // MemberPointerType *mem_ptr_type = llvm::cast<MemberPointerType>(qual_type.getTypePtr());
+ // clang::QualType pointee_type = mem_ptr_type->getPointeeType();
//
// if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
// {
@@ -3753,8 +3936,8 @@ ClangASTType::GetIndexOfChildMemberWithName (const char *name,
case clang::Type::LValueReference:
case clang::Type::RValueReference:
{
- const ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr());
- QualType pointee_type(reference_type->getPointeeType());
+ const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+ clang::QualType pointee_type(reference_type->getPointeeType());
ClangASTType pointee_clang_type (m_ast, pointee_type);
if (pointee_clang_type.IsAggregateType ())
@@ -3780,17 +3963,17 @@ ClangASTType::GetIndexOfChildMemberWithName (const char *name,
break;
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildMemberWithName (name,
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildMemberWithName (name,
omit_empty_base_classes,
child_indexes);
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetIndexOfChildMemberWithName (name,
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetIndexOfChildMemberWithName (name,
omit_empty_base_classes,
child_indexes);
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).GetIndexOfChildMemberWithName (name,
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetIndexOfChildMemberWithName (name,
omit_empty_base_classes,
child_indexes);
@@ -3811,7 +3994,7 @@ ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_cl
{
if (IsValid() && name && name[0])
{
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
@@ -3820,23 +4003,23 @@ ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_cl
case clang::Type::Record:
if (GetCompleteType ())
{
- const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
- const RecordDecl *record_decl = record_type->getDecl();
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
assert(record_decl);
uint32_t child_idx = 0;
- const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
if (cxx_record_decl)
{
- CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
base_class != base_class_end;
++base_class)
{
// Skip empty base classes
- CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+ clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
if (omit_empty_base_classes && ClangASTContext::RecordHasFields(base_class_decl) == false)
continue;
@@ -3849,8 +4032,8 @@ ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_cl
}
// Try and find a field that matches NAME
- RecordDecl::field_iterator field, field_end;
- StringRef name_sref(name);
+ clang::RecordDecl::field_iterator field, field_end;
+ llvm::StringRef name_sref(name);
for (field = record_decl->field_begin(), field_end = record_decl->field_end();
field != field_end;
++field, ++child_idx)
@@ -3866,22 +4049,22 @@ ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_cl
case clang::Type::ObjCInterface:
if (GetCompleteType())
{
- StringRef name_sref(name);
- const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr());
+ llvm::StringRef name_sref(name);
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
assert (objc_class_type);
if (objc_class_type)
{
uint32_t child_idx = 0;
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
if (class_interface_decl)
{
- ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
- ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+ clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx)
{
- const ObjCIvarDecl* ivar_decl = *ivar_pos;
+ const clang::ObjCIvarDecl* ivar_decl = *ivar_pos;
if (ivar_decl->getName().equals (name_sref))
{
@@ -3905,14 +4088,14 @@ ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_cl
case clang::Type::ObjCObjectPointer:
{
- ClangASTType pointee_clang_type (m_ast, cast<ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType());
+ ClangASTType pointee_clang_type (m_ast, llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType());
return pointee_clang_type.GetIndexOfChildWithName (name, omit_empty_base_classes);
}
break;
case clang::Type::ConstantArray:
{
- // const ConstantArrayType *array = cast<ConstantArrayType>(parent_qual_type.getTypePtr());
+ // const clang::ConstantArrayType *array = llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr());
// const uint64_t element_count = array->getSize().getLimitedValue();
//
// if (idx < element_count)
@@ -3933,8 +4116,8 @@ ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_cl
// case clang::Type::MemberPointerType:
// {
- // MemberPointerType *mem_ptr_type = cast<MemberPointerType>(qual_type.getTypePtr());
- // QualType pointee_type = mem_ptr_type->getPointeeType();
+ // MemberPointerType *mem_ptr_type = llvm::cast<MemberPointerType>(qual_type.getTypePtr());
+ // clang::QualType pointee_type = mem_ptr_type->getPointeeType();
//
// if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
// {
@@ -3948,7 +4131,7 @@ ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_cl
case clang::Type::LValueReference:
case clang::Type::RValueReference:
{
- const ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr());
+ const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
ClangASTType pointee_type (m_ast, reference_type->getPointeeType());
if (pointee_type.IsAggregateType ())
@@ -3960,7 +4143,7 @@ ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_cl
case clang::Type::Pointer:
{
- const PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
+ const clang::PointerType *pointer_type = llvm::cast<clang::PointerType>(qual_type.getTypePtr());
ClangASTType pointee_type (m_ast, pointer_type->getPointeeType());
if (pointee_type.IsAggregateType ())
@@ -3989,13 +4172,13 @@ ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_cl
break;
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetIndexOfChildWithName (name, omit_empty_base_classes);
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetIndexOfChildWithName (name, omit_empty_base_classes);
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<clang::ParenType>(qual_type)->desugar()).GetIndexOfChildWithName (name, omit_empty_base_classes);
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetIndexOfChildWithName (name, omit_empty_base_classes);
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildWithName (name, omit_empty_base_classes);
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildWithName (name, omit_empty_base_classes);
default:
break;
@@ -4010,7 +4193,7 @@ ClangASTType::GetNumTemplateArguments () const
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
@@ -4018,10 +4201,10 @@ ClangASTType::GetNumTemplateArguments () const
case clang::Type::Record:
if (GetCompleteType ())
{
- const CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
if (cxx_record_decl)
{
- const ClassTemplateSpecializationDecl *template_decl = dyn_cast<ClassTemplateSpecializationDecl>(cxx_record_decl);
+ const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(cxx_record_decl);
if (template_decl)
return template_decl->getTemplateArgs().size();
}
@@ -4029,13 +4212,13 @@ ClangASTType::GetNumTemplateArguments () const
break;
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumTemplateArguments();
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumTemplateArguments();
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetNumTemplateArguments();
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumTemplateArguments();
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<ParenType>(qual_type)->desugar()).GetNumTemplateArguments();
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumTemplateArguments();
default:
break;
@@ -4049,7 +4232,7 @@ ClangASTType::GetTemplateArgument (size_t arg_idx, lldb::TemplateArgumentKind &k
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
@@ -4057,13 +4240,13 @@ ClangASTType::GetTemplateArgument (size_t arg_idx, lldb::TemplateArgumentKind &k
case clang::Type::Record:
if (GetCompleteType ())
{
- const CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
if (cxx_record_decl)
{
- const ClassTemplateSpecializationDecl *template_decl = dyn_cast<ClassTemplateSpecializationDecl>(cxx_record_decl);
+ const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(cxx_record_decl);
if (template_decl && arg_idx < template_decl->getTemplateArgs().size())
{
- const TemplateArgument &template_arg = template_decl->getTemplateArgs()[arg_idx];
+ const clang::TemplateArgument &template_arg = template_decl->getTemplateArgs()[arg_idx];
switch (template_arg.getKind())
{
case clang::TemplateArgument::Null:
@@ -4099,7 +4282,7 @@ ClangASTType::GetTemplateArgument (size_t arg_idx, lldb::TemplateArgumentKind &k
return ClangASTType();
default:
- assert (!"Unhandled TemplateArgument::ArgKind");
+ assert (!"Unhandled clang::TemplateArgument::ArgKind");
break;
}
}
@@ -4108,13 +4291,13 @@ ClangASTType::GetTemplateArgument (size_t arg_idx, lldb::TemplateArgumentKind &k
break;
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetTemplateArgument (arg_idx, kind);
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetTemplateArgument (arg_idx, kind);
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetTemplateArgument (arg_idx, kind);
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetTemplateArgument (arg_idx, kind);
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<ParenType>(qual_type)->desugar()).GetTemplateArgument (arg_idx, kind);
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetTemplateArgument (arg_idx, kind);
default:
break;
@@ -4125,15 +4308,15 @@ ClangASTType::GetTemplateArgument (size_t arg_idx, lldb::TemplateArgumentKind &k
}
static bool
-IsOperator (const char *name, OverloadedOperatorKind &op_kind)
+IsOperator (const char *name, clang::OverloadedOperatorKind &op_kind)
{
- if (name == NULL || name[0] == '\0')
+ if (name == nullptr || name[0] == '\0')
return false;
#define OPERATOR_PREFIX "operator"
#define OPERATOR_PREFIX_LENGTH (sizeof (OPERATOR_PREFIX) - 1)
- const char *post_op_name = NULL;
+ const char *post_op_name = nullptr;
bool no_space = true;
@@ -4153,7 +4336,7 @@ IsOperator (const char *name, OverloadedOperatorKind &op_kind)
// This is an operator, set the overloaded operator kind to invalid
// in case this is a conversion operator...
- op_kind = NUM_OVERLOADED_OPERATORS;
+ op_kind = clang::NUM_OVERLOADED_OPERATORS;
switch (post_op_name[0])
{
@@ -4165,204 +4348,197 @@ IsOperator (const char *name, OverloadedOperatorKind &op_kind)
if (no_space)
return false;
if (strcmp (post_op_name, "new") == 0)
- op_kind = OO_New;
+ op_kind = clang::OO_New;
else if (strcmp (post_op_name, "new[]") == 0)
- op_kind = OO_Array_New;
+ op_kind = clang::OO_Array_New;
break;
case 'd':
if (no_space)
return false;
if (strcmp (post_op_name, "delete") == 0)
- op_kind = OO_Delete;
+ op_kind = clang::OO_Delete;
else if (strcmp (post_op_name, "delete[]") == 0)
- op_kind = OO_Array_Delete;
+ op_kind = clang::OO_Array_Delete;
break;
case '+':
if (post_op_name[1] == '\0')
- op_kind = OO_Plus;
+ op_kind = clang::OO_Plus;
else if (post_op_name[2] == '\0')
{
if (post_op_name[1] == '=')
- op_kind = OO_PlusEqual;
+ op_kind = clang::OO_PlusEqual;
else if (post_op_name[1] == '+')
- op_kind = OO_PlusPlus;
+ op_kind = clang::OO_PlusPlus;
}
break;
case '-':
if (post_op_name[1] == '\0')
- op_kind = OO_Minus;
+ op_kind = clang::OO_Minus;
else if (post_op_name[2] == '\0')
{
switch (post_op_name[1])
{
- case '=': op_kind = OO_MinusEqual; break;
- case '-': op_kind = OO_MinusMinus; break;
- case '>': op_kind = OO_Arrow; break;
+ case '=': op_kind = clang::OO_MinusEqual; break;
+ case '-': op_kind = clang::OO_MinusMinus; break;
+ case '>': op_kind = clang::OO_Arrow; break;
}
}
else if (post_op_name[3] == '\0')
{
if (post_op_name[2] == '*')
- op_kind = OO_ArrowStar; break;
+ op_kind = clang::OO_ArrowStar; break;
}
break;
case '*':
if (post_op_name[1] == '\0')
- op_kind = OO_Star;
+ op_kind = clang::OO_Star;
else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = OO_StarEqual;
+ op_kind = clang::OO_StarEqual;
break;
case '/':
if (post_op_name[1] == '\0')
- op_kind = OO_Slash;
+ op_kind = clang::OO_Slash;
else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = OO_SlashEqual;
+ op_kind = clang::OO_SlashEqual;
break;
case '%':
if (post_op_name[1] == '\0')
- op_kind = OO_Percent;
+ op_kind = clang::OO_Percent;
else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = OO_PercentEqual;
+ op_kind = clang::OO_PercentEqual;
break;
case '^':
if (post_op_name[1] == '\0')
- op_kind = OO_Caret;
+ op_kind = clang::OO_Caret;
else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = OO_CaretEqual;
+ op_kind = clang::OO_CaretEqual;
break;
case '&':
if (post_op_name[1] == '\0')
- op_kind = OO_Amp;
+ op_kind = clang::OO_Amp;
else if (post_op_name[2] == '\0')
{
switch (post_op_name[1])
{
- case '=': op_kind = OO_AmpEqual; break;
- case '&': op_kind = OO_AmpAmp; break;
+ case '=': op_kind = clang::OO_AmpEqual; break;
+ case '&': op_kind = clang::OO_AmpAmp; break;
}
}
break;
case '|':
if (post_op_name[1] == '\0')
- op_kind = OO_Pipe;
+ op_kind = clang::OO_Pipe;
else if (post_op_name[2] == '\0')
{
switch (post_op_name[1])
{
- case '=': op_kind = OO_PipeEqual; break;
- case '|': op_kind = OO_PipePipe; break;
+ case '=': op_kind = clang::OO_PipeEqual; break;
+ case '|': op_kind = clang::OO_PipePipe; break;
}
}
break;
case '~':
if (post_op_name[1] == '\0')
- op_kind = OO_Tilde;
+ op_kind = clang::OO_Tilde;
break;
case '!':
if (post_op_name[1] == '\0')
- op_kind = OO_Exclaim;
+ op_kind = clang::OO_Exclaim;
else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = OO_ExclaimEqual;
+ op_kind = clang::OO_ExclaimEqual;
break;
case '=':
if (post_op_name[1] == '\0')
- op_kind = OO_Equal;
+ op_kind = clang::OO_Equal;
else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = OO_EqualEqual;
+ op_kind = clang::OO_EqualEqual;
break;
case '<':
if (post_op_name[1] == '\0')
- op_kind = OO_Less;
+ op_kind = clang::OO_Less;
else if (post_op_name[2] == '\0')
{
switch (post_op_name[1])
{
- case '<': op_kind = OO_LessLess; break;
- case '=': op_kind = OO_LessEqual; break;
+ case '<': op_kind = clang::OO_LessLess; break;
+ case '=': op_kind = clang::OO_LessEqual; break;
}
}
else if (post_op_name[3] == '\0')
{
if (post_op_name[2] == '=')
- op_kind = OO_LessLessEqual;
+ op_kind = clang::OO_LessLessEqual;
}
break;
case '>':
if (post_op_name[1] == '\0')
- op_kind = OO_Greater;
+ op_kind = clang::OO_Greater;
else if (post_op_name[2] == '\0')
{
switch (post_op_name[1])
{
- case '>': op_kind = OO_GreaterGreater; break;
- case '=': op_kind = OO_GreaterEqual; break;
+ case '>': op_kind = clang::OO_GreaterGreater; break;
+ case '=': op_kind = clang::OO_GreaterEqual; break;
}
}
else if (post_op_name[1] == '>' &&
post_op_name[2] == '=' &&
post_op_name[3] == '\0')
{
- op_kind = OO_GreaterGreaterEqual;
+ op_kind = clang::OO_GreaterGreaterEqual;
}
break;
case ',':
if (post_op_name[1] == '\0')
- op_kind = OO_Comma;
+ op_kind = clang::OO_Comma;
break;
case '(':
if (post_op_name[1] == ')' && post_op_name[2] == '\0')
- op_kind = OO_Call;
+ op_kind = clang::OO_Call;
break;
case '[':
if (post_op_name[1] == ']' && post_op_name[2] == '\0')
- op_kind = OO_Subscript;
+ op_kind = clang::OO_Subscript;
break;
}
return true;
}
-static inline bool
-check_op_param (uint32_t op_kind, bool unary, bool binary, uint32_t num_params)
+clang::EnumDecl *
+ClangASTType::GetAsEnumDecl () const
{
- // Special-case call since it can take any number of operands
- if(op_kind == OO_Call)
- return true;
-
- // The parameter count doens't include "this"
- if (num_params == 0)
- return unary;
- if (num_params == 1)
- return binary;
- else
- return false;
+ const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType());
+ if (enum_type)
+ return enum_type->getDecl();
+ return NULL;
}
clang::RecordDecl *
ClangASTType::GetAsRecordDecl () const
{
- const RecordType *record_type = dyn_cast<RecordType>(GetCanonicalQualType());
+ const clang::RecordType *record_type = llvm::dyn_cast<clang::RecordType>(GetCanonicalQualType());
if (record_type)
return record_type->getDecl();
- return NULL;
+ return nullptr;
}
clang::CXXRecordDecl *
@@ -4371,13 +4547,13 @@ ClangASTType::GetAsCXXRecordDecl () const
return GetCanonicalQualType()->getAsCXXRecordDecl();
}
-ObjCInterfaceDecl *
+clang::ObjCInterfaceDecl *
ClangASTType::GetAsObjCInterfaceDecl () const
{
- const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(GetCanonicalQualType());
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(GetCanonicalQualType());
if (objc_class_type)
return objc_class_type->getInterface();
- return NULL;
+ return nullptr;
}
clang::FieldDecl *
@@ -4387,37 +4563,37 @@ ClangASTType::AddFieldToRecordType (const char *name,
uint32_t bitfield_bit_size)
{
if (!IsValid() || !field_clang_type.IsValid())
- return NULL;
+ return nullptr;
- FieldDecl *field = NULL;
+ clang::FieldDecl *field = nullptr;
- clang::Expr *bit_width = NULL;
+ clang::Expr *bit_width = nullptr;
if (bitfield_bit_size != 0)
{
- APInt bitfield_bit_size_apint(m_ast->getTypeSize(m_ast->IntTy), bitfield_bit_size);
- bit_width = new (*m_ast)IntegerLiteral (*m_ast, bitfield_bit_size_apint, m_ast->IntTy, SourceLocation());
+ llvm::APInt bitfield_bit_size_apint(m_ast->getTypeSize(m_ast->IntTy), bitfield_bit_size);
+ bit_width = new (*m_ast)clang::IntegerLiteral (*m_ast, bitfield_bit_size_apint, m_ast->IntTy, clang::SourceLocation());
}
- RecordDecl *record_decl = GetAsRecordDecl ();
+ clang::RecordDecl *record_decl = GetAsRecordDecl ();
if (record_decl)
{
- field = FieldDecl::Create (*m_ast,
- record_decl,
- SourceLocation(),
- SourceLocation(),
- name ? &m_ast->Idents.get(name) : NULL, // Identifier
- field_clang_type.GetQualType(), // Field type
- NULL, // TInfo *
- bit_width, // BitWidth
- false, // Mutable
- ICIS_NoInit); // HasInit
+ field = clang::FieldDecl::Create (*m_ast,
+ record_decl,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ name ? &m_ast->Idents.get(name) : nullptr, // Identifier
+ field_clang_type.GetQualType(), // Field type
+ nullptr, // TInfo *
+ bit_width, // BitWidth
+ false, // Mutable
+ clang::ICIS_NoInit); // HasInit
if (!name)
{
// Determine whether this field corresponds to an anonymous
// struct or union.
- if (const TagType *TagT = field->getType()->getAs<TagType>()) {
- if (RecordDecl *Rec = dyn_cast<RecordDecl>(TagT->getDecl()))
+ if (const clang::TagType *TagT = field->getType()->getAs<clang::TagType>()) {
+ if (clang::RecordDecl *Rec = llvm::dyn_cast<clang::RecordDecl>(TagT->getDecl()))
if (!Rec->getDeclName()) {
Rec->setAnonymousStructOrUnion(true);
field->setImplicit();
@@ -4439,7 +4615,7 @@ ClangASTType::AddFieldToRecordType (const char *name,
}
else
{
- ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl ();
+ clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl ();
if (class_interface_decl)
{
@@ -4447,13 +4623,13 @@ ClangASTType::AddFieldToRecordType (const char *name,
field_clang_type.GetCompleteType();
- field = ObjCIvarDecl::Create (*m_ast,
+ field = clang::ObjCIvarDecl::Create (*m_ast,
class_interface_decl,
- SourceLocation(),
- SourceLocation(),
- name ? &m_ast->Idents.get(name) : NULL, // Identifier
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ name ? &m_ast->Idents.get(name) : nullptr, // Identifier
field_clang_type.GetQualType(), // Field type
- NULL, // TypeSourceInfo *
+ nullptr, // TypeSourceInfo *
ConvertAccessTypeToObjCIvarAccessControl (access),
bit_width,
is_synthesized);
@@ -4474,49 +4650,49 @@ ClangASTType::AddFieldToRecordType (const char *name,
void
ClangASTType::BuildIndirectFields ()
{
- RecordDecl *record_decl = GetAsRecordDecl();
+ clang::RecordDecl *record_decl = GetAsRecordDecl();
if (!record_decl)
return;
- typedef llvm::SmallVector <IndirectFieldDecl *, 1> IndirectFieldVector;
+ typedef llvm::SmallVector <clang::IndirectFieldDecl *, 1> IndirectFieldVector;
IndirectFieldVector indirect_fields;
- RecordDecl::field_iterator field_pos;
- RecordDecl::field_iterator field_end_pos = record_decl->field_end();
- RecordDecl::field_iterator last_field_pos = field_end_pos;
+ clang::RecordDecl::field_iterator field_pos;
+ clang::RecordDecl::field_iterator field_end_pos = record_decl->field_end();
+ clang::RecordDecl::field_iterator last_field_pos = field_end_pos;
for (field_pos = record_decl->field_begin(); field_pos != field_end_pos; last_field_pos = field_pos++)
{
if (field_pos->isAnonymousStructOrUnion())
{
- QualType field_qual_type = field_pos->getType();
+ clang::QualType field_qual_type = field_pos->getType();
- const RecordType *field_record_type = field_qual_type->getAs<RecordType>();
+ const clang::RecordType *field_record_type = field_qual_type->getAs<clang::RecordType>();
if (!field_record_type)
continue;
- RecordDecl *field_record_decl = field_record_type->getDecl();
+ clang::RecordDecl *field_record_decl = field_record_type->getDecl();
if (!field_record_decl)
continue;
- for (RecordDecl::decl_iterator di = field_record_decl->decls_begin(), de = field_record_decl->decls_end();
+ for (clang::RecordDecl::decl_iterator di = field_record_decl->decls_begin(), de = field_record_decl->decls_end();
di != de;
++di)
{
- if (FieldDecl *nested_field_decl = dyn_cast<FieldDecl>(*di))
+ if (clang::FieldDecl *nested_field_decl = llvm::dyn_cast<clang::FieldDecl>(*di))
{
- NamedDecl **chain = new (*m_ast) NamedDecl*[2];
+ clang::NamedDecl **chain = new (*m_ast) clang::NamedDecl*[2];
chain[0] = *field_pos;
chain[1] = nested_field_decl;
- IndirectFieldDecl *indirect_field = IndirectFieldDecl::Create(*m_ast,
- record_decl,
- SourceLocation(),
- nested_field_decl->getIdentifier(),
- nested_field_decl->getType(),
- chain,
- 2);
+ clang::IndirectFieldDecl *indirect_field = clang::IndirectFieldDecl::Create(*m_ast,
+ record_decl,
+ clang::SourceLocation(),
+ nested_field_decl->getIdentifier(),
+ nested_field_decl->getType(),
+ chain,
+ 2);
indirect_field->setImplicit();
@@ -4525,14 +4701,14 @@ ClangASTType::BuildIndirectFields ()
indirect_fields.push_back(indirect_field);
}
- else if (IndirectFieldDecl *nested_indirect_field_decl = dyn_cast<IndirectFieldDecl>(*di))
+ else if (clang::IndirectFieldDecl *nested_indirect_field_decl = llvm::dyn_cast<clang::IndirectFieldDecl>(*di))
{
int nested_chain_size = nested_indirect_field_decl->getChainingSize();
- NamedDecl **chain = new (*m_ast) NamedDecl*[nested_chain_size + 1];
+ clang::NamedDecl **chain = new (*m_ast) clang::NamedDecl*[nested_chain_size + 1];
chain[0] = *field_pos;
int chain_index = 1;
- for (IndirectFieldDecl::chain_iterator nci = nested_indirect_field_decl->chain_begin(),
+ for (clang::IndirectFieldDecl::chain_iterator nci = nested_indirect_field_decl->chain_begin(),
nce = nested_indirect_field_decl->chain_end();
nci < nce;
++nci)
@@ -4541,13 +4717,13 @@ ClangASTType::BuildIndirectFields ()
chain_index++;
}
- IndirectFieldDecl *indirect_field = IndirectFieldDecl::Create(*m_ast,
- record_decl,
- SourceLocation(),
- nested_indirect_field_decl->getIdentifier(),
- nested_indirect_field_decl->getType(),
- chain,
- nested_chain_size + 1);
+ clang::IndirectFieldDecl *indirect_field = clang::IndirectFieldDecl::Create(*m_ast,
+ record_decl,
+ clang::SourceLocation(),
+ nested_indirect_field_decl->getIdentifier(),
+ nested_indirect_field_decl->getType(),
+ chain,
+ nested_chain_size + 1);
indirect_field->setImplicit();
@@ -4581,22 +4757,22 @@ ClangASTType::AddVariableToRecordType (const char *name,
const ClangASTType &var_type,
AccessType access)
{
- clang::VarDecl *var_decl = NULL;
+ clang::VarDecl *var_decl = nullptr;
if (!IsValid() || !var_type.IsValid())
- return NULL;
+ return nullptr;
- RecordDecl *record_decl = GetAsRecordDecl ();
+ clang::RecordDecl *record_decl = GetAsRecordDecl ();
if (record_decl)
{
- var_decl = VarDecl::Create (*m_ast, // ASTContext &
- record_decl, // DeclContext *
- SourceLocation(), // SourceLocation StartLoc
- SourceLocation(), // SourceLocation IdLoc
- name ? &m_ast->Idents.get(name) : NULL, // IdentifierInfo *
- var_type.GetQualType(), // Variable QualType
- NULL, // TypeSourceInfo *
- SC_Static); // StorageClass
+ var_decl = clang::VarDecl::Create (*m_ast, // ASTContext &
+ record_decl, // DeclContext *
+ clang::SourceLocation(), // clang::SourceLocation StartLoc
+ clang::SourceLocation(), // clang::SourceLocation IdLoc
+ name ? &m_ast->Idents.get(name) : nullptr, // clang::IdentifierInfo *
+ var_type.GetQualType(), // Variable clang::QualType
+ nullptr, // TypeSourceInfo *
+ clang::SC_Static); // StorageClass
if (var_decl)
{
var_decl->setAccess(ClangASTContext::ConvertAccessTypeToAccessSpecifier (access));
@@ -4611,7 +4787,7 @@ ClangASTType::AddVariableToRecordType (const char *name,
}
-CXXMethodDecl *
+clang::CXXMethodDecl *
ClangASTType::AddMethodToCXXRecordType (const char *name,
const ClangASTType &method_clang_type,
lldb::AccessType access,
@@ -4622,74 +4798,74 @@ ClangASTType::AddMethodToCXXRecordType (const char *name,
bool is_attr_used,
bool is_artificial)
{
- if (!IsValid() || !method_clang_type.IsValid() || name == NULL || name[0] == '\0')
- return NULL;
+ if (!IsValid() || !method_clang_type.IsValid() || name == nullptr || name[0] == '\0')
+ return nullptr;
- QualType record_qual_type(GetCanonicalQualType());
+ clang::QualType record_qual_type(GetCanonicalQualType());
- CXXRecordDecl *cxx_record_decl = record_qual_type->getAsCXXRecordDecl();
+ clang::CXXRecordDecl *cxx_record_decl = record_qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl == NULL)
- return NULL;
+ if (cxx_record_decl == nullptr)
+ return nullptr;
- QualType method_qual_type (method_clang_type.GetQualType());
+ clang::QualType method_qual_type (method_clang_type.GetQualType());
- CXXMethodDecl *cxx_method_decl = NULL;
+ clang::CXXMethodDecl *cxx_method_decl = nullptr;
- DeclarationName decl_name (&m_ast->Idents.get(name));
+ clang::DeclarationName decl_name (&m_ast->Idents.get(name));
- const clang::FunctionType *function_type = dyn_cast<FunctionType>(method_qual_type.getTypePtr());
+ const clang::FunctionType *function_type = llvm::dyn_cast<clang::FunctionType>(method_qual_type.getTypePtr());
- if (function_type == NULL)
- return NULL;
+ if (function_type == nullptr)
+ return nullptr;
- const FunctionProtoType *method_function_prototype (dyn_cast<FunctionProtoType>(function_type));
+ const clang::FunctionProtoType *method_function_prototype (llvm::dyn_cast<clang::FunctionProtoType>(function_type));
if (!method_function_prototype)
- return NULL;
+ return nullptr;
unsigned int num_params = method_function_prototype->getNumParams();
- CXXDestructorDecl *cxx_dtor_decl(NULL);
- CXXConstructorDecl *cxx_ctor_decl(NULL);
+ clang::CXXDestructorDecl *cxx_dtor_decl(nullptr);
+ clang::CXXConstructorDecl *cxx_ctor_decl(nullptr);
if (is_artificial)
- return NULL; // skip everything artificial
+ return nullptr; // skip everything artificial
if (name[0] == '~')
{
- cxx_dtor_decl = CXXDestructorDecl::Create (*m_ast,
- cxx_record_decl,
- SourceLocation(),
- DeclarationNameInfo (m_ast->DeclarationNames.getCXXDestructorName (m_ast->getCanonicalType (record_qual_type)), SourceLocation()),
- method_qual_type,
- NULL,
- is_inline,
- is_artificial);
+ cxx_dtor_decl = clang::CXXDestructorDecl::Create (*m_ast,
+ cxx_record_decl,
+ clang::SourceLocation(),
+ clang::DeclarationNameInfo (m_ast->DeclarationNames.getCXXDestructorName (m_ast->getCanonicalType (record_qual_type)), clang::SourceLocation()),
+ method_qual_type,
+ nullptr,
+ is_inline,
+ is_artificial);
cxx_method_decl = cxx_dtor_decl;
}
else if (decl_name == cxx_record_decl->getDeclName())
{
- cxx_ctor_decl = CXXConstructorDecl::Create (*m_ast,
- cxx_record_decl,
- SourceLocation(),
- DeclarationNameInfo (m_ast->DeclarationNames.getCXXConstructorName (m_ast->getCanonicalType (record_qual_type)), SourceLocation()),
- method_qual_type,
- NULL, // TypeSourceInfo *
- is_explicit,
- is_inline,
- is_artificial,
- false /*is_constexpr*/);
+ cxx_ctor_decl = clang::CXXConstructorDecl::Create (*m_ast,
+ cxx_record_decl,
+ clang::SourceLocation(),
+ clang::DeclarationNameInfo (m_ast->DeclarationNames.getCXXConstructorName (m_ast->getCanonicalType (record_qual_type)), clang::SourceLocation()),
+ method_qual_type,
+ nullptr, // TypeSourceInfo *
+ is_explicit,
+ is_inline,
+ is_artificial,
+ false /*is_constexpr*/);
cxx_method_decl = cxx_ctor_decl;
}
else
{
- clang::StorageClass SC = is_static ? SC_Static : SC_None;
- OverloadedOperatorKind op_kind = NUM_OVERLOADED_OPERATORS;
+ clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None;
+ clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
if (IsOperator (name, op_kind))
{
- if (op_kind != NUM_OVERLOADED_OPERATORS)
+ if (op_kind != clang::NUM_OVERLOADED_OPERATORS)
{
// Check the number of operator parameters. Sometimes we have
// seen bad DWARF that doesn't correctly describe operators and
@@ -4697,50 +4873,50 @@ ClangASTType::AddMethodToCXXRecordType (const char *name,
// will assert and crash, so we need to make sure things are
// acceptable.
if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount (op_kind, num_params))
- return NULL;
- cxx_method_decl = CXXMethodDecl::Create (*m_ast,
- cxx_record_decl,
- SourceLocation(),
- DeclarationNameInfo (m_ast->DeclarationNames.getCXXOperatorName (op_kind), SourceLocation()),
- method_qual_type,
- NULL, // TypeSourceInfo *
- SC,
- is_inline,
- false /*is_constexpr*/,
- SourceLocation());
+ return nullptr;
+ cxx_method_decl = clang::CXXMethodDecl::Create (*m_ast,
+ cxx_record_decl,
+ clang::SourceLocation(),
+ clang::DeclarationNameInfo (m_ast->DeclarationNames.getCXXOperatorName (op_kind), clang::SourceLocation()),
+ method_qual_type,
+ nullptr, // TypeSourceInfo *
+ SC,
+ is_inline,
+ false /*is_constexpr*/,
+ clang::SourceLocation());
}
else if (num_params == 0)
{
// Conversion operators don't take params...
- cxx_method_decl = CXXConversionDecl::Create (*m_ast,
- cxx_record_decl,
- SourceLocation(),
- DeclarationNameInfo (m_ast->DeclarationNames.getCXXConversionFunctionName (m_ast->getCanonicalType (function_type->getReturnType())), SourceLocation()),
- method_qual_type,
- NULL, // TypeSourceInfo *
- is_inline,
- is_explicit,
- false /*is_constexpr*/,
- SourceLocation());
+ cxx_method_decl = clang::CXXConversionDecl::Create (*m_ast,
+ cxx_record_decl,
+ clang::SourceLocation(),
+ clang::DeclarationNameInfo (m_ast->DeclarationNames.getCXXConversionFunctionName (m_ast->getCanonicalType (function_type->getReturnType())), clang::SourceLocation()),
+ method_qual_type,
+ nullptr, // TypeSourceInfo *
+ is_inline,
+ is_explicit,
+ false /*is_constexpr*/,
+ clang::SourceLocation());
}
}
- if (cxx_method_decl == NULL)
+ if (cxx_method_decl == nullptr)
{
- cxx_method_decl = CXXMethodDecl::Create (*m_ast,
- cxx_record_decl,
- SourceLocation(),
- DeclarationNameInfo (decl_name, SourceLocation()),
- method_qual_type,
- NULL, // TypeSourceInfo *
- SC,
- is_inline,
- false /*is_constexpr*/,
- SourceLocation());
+ cxx_method_decl = clang::CXXMethodDecl::Create (*m_ast,
+ cxx_record_decl,
+ clang::SourceLocation(),
+ clang::DeclarationNameInfo (decl_name, clang::SourceLocation()),
+ method_qual_type,
+ nullptr, // TypeSourceInfo *
+ SC,
+ is_inline,
+ false /*is_constexpr*/,
+ clang::SourceLocation());
}
}
- AccessSpecifier access_specifier = ClangASTContext::ConvertAccessTypeToAccessSpecifier (access);
+ clang::AccessSpecifier access_specifier = ClangASTContext::ConvertAccessTypeToAccessSpecifier (access);
cxx_method_decl->setAccess (access_specifier);
cxx_method_decl->setVirtualAsWritten (is_virtual);
@@ -4750,24 +4926,24 @@ ClangASTType::AddMethodToCXXRecordType (const char *name,
// Populate the method decl with parameter decls
- llvm::SmallVector<ParmVarDecl *, 12> params;
+ llvm::SmallVector<clang::ParmVarDecl *, 12> params;
for (unsigned param_index = 0;
param_index < num_params;
++param_index)
{
- params.push_back (ParmVarDecl::Create (*m_ast,
- cxx_method_decl,
- SourceLocation(),
- SourceLocation(),
- NULL, // anonymous
- method_function_prototype->getParamType(param_index),
- NULL,
- SC_None,
- NULL));
+ params.push_back (clang::ParmVarDecl::Create (*m_ast,
+ cxx_method_decl,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ nullptr, // anonymous
+ method_function_prototype->getParamType(param_index),
+ nullptr,
+ clang::SC_None,
+ nullptr));
}
- cxx_method_decl->setParams (ArrayRef<ParmVarDecl*>(params));
+ cxx_method_decl->setParams (llvm::ArrayRef<clang::ParmVarDecl*>(params));
cxx_record_decl->addDecl (cxx_method_decl);
@@ -4823,36 +4999,36 @@ ClangASTType::AddMethodToCXXRecordType (const char *name,
#pragma mark C++ Base Classes
-CXXBaseSpecifier *
+clang::CXXBaseSpecifier *
ClangASTType::CreateBaseClassSpecifier (AccessType access, bool is_virtual, bool base_of_class)
{
if (IsValid())
- return new CXXBaseSpecifier (SourceRange(),
- is_virtual,
- base_of_class,
- ClangASTContext::ConvertAccessTypeToAccessSpecifier (access),
- m_ast->getTrivialTypeSourceInfo (GetQualType()),
- SourceLocation());
- return NULL;
+ return new clang::CXXBaseSpecifier (clang::SourceRange(),
+ is_virtual,
+ base_of_class,
+ ClangASTContext::ConvertAccessTypeToAccessSpecifier (access),
+ m_ast->getTrivialTypeSourceInfo (GetQualType()),
+ clang::SourceLocation());
+ return nullptr;
}
void
-ClangASTType::DeleteBaseClassSpecifiers (CXXBaseSpecifier **base_classes, unsigned num_base_classes)
+ClangASTType::DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes, unsigned num_base_classes)
{
for (unsigned i=0; i<num_base_classes; ++i)
{
delete base_classes[i];
- base_classes[i] = NULL;
+ base_classes[i] = nullptr;
}
}
bool
-ClangASTType::SetBaseClassesForClassType (CXXBaseSpecifier const * const *base_classes,
+ClangASTType::SetBaseClassesForClassType (clang::CXXBaseSpecifier const * const *base_classes,
unsigned num_base_classes)
{
if (IsValid())
{
- CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl();
+ clang::CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl();
if (cxx_record_decl)
{
cxx_record_decl->setBases(base_classes, num_base_classes);
@@ -4867,8 +5043,8 @@ ClangASTType::SetObjCSuperClass (const ClangASTType &superclass_clang_type)
{
if (IsValid() && superclass_clang_type.IsValid())
{
- ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl ();
- ObjCInterfaceDecl *super_interface_decl = superclass_clang_type.GetAsObjCInterfaceDecl ();
+ clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl ();
+ clang::ObjCInterfaceDecl *super_interface_decl = superclass_clang_type.GetAsObjCInterfaceDecl ();
if (class_interface_decl && super_interface_decl)
{
class_interface_decl->setSuperClass(super_interface_decl);
@@ -4881,16 +5057,16 @@ ClangASTType::SetObjCSuperClass (const ClangASTType &superclass_clang_type)
bool
ClangASTType::AddObjCClassProperty (const char *property_name,
const ClangASTType &property_clang_type,
- ObjCIvarDecl *ivar_decl,
+ clang::ObjCIvarDecl *ivar_decl,
const char *property_setter_name,
const char *property_getter_name,
uint32_t property_attributes,
ClangASTMetadata *metadata)
{
- if (!IsValid() || !property_clang_type.IsValid() || property_name == NULL || property_name[0] == '\0')
+ if (!IsValid() || !property_clang_type.IsValid() || property_name == nullptr || property_name[0] == '\0')
return false;
- ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl ();
+ clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl ();
if (class_interface_decl)
{
@@ -4909,13 +5085,13 @@ ClangASTType::AddObjCClassProperty (const char *property_name,
else
prop_type_source = m_ast->getTrivialTypeSourceInfo (property_clang_type.GetQualType());
- ObjCPropertyDecl *property_decl = ObjCPropertyDecl::Create (*m_ast,
- class_interface_decl,
- SourceLocation(), // Source Location
- &m_ast->Idents.get(property_name),
- SourceLocation(), //Source Location for AT
- SourceLocation(), //Source location for (
- prop_type_source);
+ clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create (*m_ast,
+ class_interface_decl,
+ clang::SourceLocation(), // Source Location
+ &m_ast->Idents.get(property_name),
+ clang::SourceLocation(), //Source Location for AT
+ clang::SourceLocation(), //Source location for (
+ prop_type_source);
if (property_decl)
{
@@ -4924,9 +5100,9 @@ ClangASTType::AddObjCClassProperty (const char *property_name,
class_interface_decl->addDecl (property_decl);
- Selector setter_sel, getter_sel;
+ clang::Selector setter_sel, getter_sel;
- if (property_setter_name != NULL)
+ if (property_setter_name != nullptr)
{
std::string property_setter_no_colon(property_setter_name, strlen(property_setter_name) - 1);
clang::IdentifierInfo *setter_ident = &m_ast->Idents.get(property_setter_no_colon.c_str());
@@ -4943,7 +5119,7 @@ ClangASTType::AddObjCClassProperty (const char *property_name,
property_decl->setSetterName(setter_sel);
property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_setter);
- if (property_getter_name != NULL)
+ if (property_getter_name != nullptr)
{
clang::IdentifierInfo *getter_ident = &m_ast->Idents.get(property_getter_name);
getter_sel = m_ast->Selectors.getSelector(0, &getter_ident);
@@ -4979,75 +5155,75 @@ ClangASTType::AddObjCClassProperty (const char *property_name,
const bool isSynthesized = false;
const bool isImplicitlyDeclared = true;
const bool isDefined = false;
- const ObjCMethodDecl::ImplementationControl impControl = ObjCMethodDecl::None;
+ const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None;
const bool HasRelatedResultType = false;
- ObjCMethodDecl *getter = ObjCMethodDecl::Create (*m_ast,
- SourceLocation(),
- SourceLocation(),
- getter_sel,
- property_clang_type_to_access.GetQualType(),
- NULL,
- class_interface_decl,
- isInstance,
- isVariadic,
- isSynthesized,
- isImplicitlyDeclared,
- isDefined,
- impControl,
- HasRelatedResultType);
+ clang::ObjCMethodDecl *getter = clang::ObjCMethodDecl::Create (*m_ast,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ getter_sel,
+ property_clang_type_to_access.GetQualType(),
+ nullptr,
+ class_interface_decl,
+ isInstance,
+ isVariadic,
+ isSynthesized,
+ isImplicitlyDeclared,
+ isDefined,
+ impControl,
+ HasRelatedResultType);
if (getter && metadata)
ClangASTContext::SetMetadata(m_ast, getter, *metadata);
- getter->setMethodParams(*m_ast, ArrayRef<ParmVarDecl*>(), ArrayRef<SourceLocation>());
+ getter->setMethodParams(*m_ast, llvm::ArrayRef<clang::ParmVarDecl*>(), llvm::ArrayRef<clang::SourceLocation>());
class_interface_decl->addDecl(getter);
}
if (!setter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(setter_sel))
{
- QualType result_type = m_ast->VoidTy;
+ clang::QualType result_type = m_ast->VoidTy;
const bool isInstance = true;
const bool isVariadic = false;
const bool isSynthesized = false;
const bool isImplicitlyDeclared = true;
const bool isDefined = false;
- const ObjCMethodDecl::ImplementationControl impControl = ObjCMethodDecl::None;
+ const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None;
const bool HasRelatedResultType = false;
- ObjCMethodDecl *setter = ObjCMethodDecl::Create (*m_ast,
- SourceLocation(),
- SourceLocation(),
- setter_sel,
- result_type,
- NULL,
- class_interface_decl,
- isInstance,
- isVariadic,
- isSynthesized,
- isImplicitlyDeclared,
- isDefined,
- impControl,
- HasRelatedResultType);
+ clang::ObjCMethodDecl *setter = clang::ObjCMethodDecl::Create (*m_ast,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ setter_sel,
+ result_type,
+ nullptr,
+ class_interface_decl,
+ isInstance,
+ isVariadic,
+ isSynthesized,
+ isImplicitlyDeclared,
+ isDefined,
+ impControl,
+ HasRelatedResultType);
if (setter && metadata)
ClangASTContext::SetMetadata(m_ast, setter, *metadata);
- llvm::SmallVector<ParmVarDecl *, 1> params;
+ llvm::SmallVector<clang::ParmVarDecl *, 1> params;
- params.push_back (ParmVarDecl::Create (*m_ast,
- setter,
- SourceLocation(),
- SourceLocation(),
- NULL, // anonymous
- property_clang_type_to_access.GetQualType(),
- NULL,
- SC_Auto,
- NULL));
+ params.push_back (clang::ParmVarDecl::Create (*m_ast,
+ setter,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ nullptr, // anonymous
+ property_clang_type_to_access.GetQualType(),
+ nullptr,
+ clang::SC_Auto,
+ nullptr));
- setter->setMethodParams(*m_ast, ArrayRef<ParmVarDecl*>(params), ArrayRef<SourceLocation>());
+ setter->setMethodParams(*m_ast, llvm::ArrayRef<clang::ParmVarDecl*>(params), llvm::ArrayRef<clang::SourceLocation>());
class_interface_decl->addDecl(setter);
}
@@ -5062,33 +5238,33 @@ ClangASTType::AddObjCClassProperty (const char *property_name,
bool
ClangASTType::IsObjCClassTypeAndHasIVars (bool check_superclass) const
{
- ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl ();
+ clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl ();
if (class_interface_decl)
return ObjCDeclHasIVars (class_interface_decl, check_superclass);
return false;
}
-ObjCMethodDecl *
+clang::ObjCMethodDecl *
ClangASTType::AddMethodToObjCObjectType (const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]")
const ClangASTType &method_clang_type,
lldb::AccessType access,
bool is_artificial)
{
if (!IsValid() || !method_clang_type.IsValid())
- return NULL;
+ return nullptr;
- ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl();
+ clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl();
- if (class_interface_decl == NULL)
- return NULL;
+ if (class_interface_decl == nullptr)
+ return nullptr;
const char *selector_start = ::strchr (name, ' ');
- if (selector_start == NULL)
- return NULL;
+ if (selector_start == nullptr)
+ return nullptr;
selector_start++;
- llvm::SmallVector<IdentifierInfo *, 12> selector_idents;
+ llvm::SmallVector<clang::IdentifierInfo *, 12> selector_idents;
size_t len = 0;
const char *start;
@@ -5103,79 +5279,79 @@ ClangASTType::AddMethodToObjCObjectType (const char *name, // the full symbol n
bool has_arg = (start[len] == ':');
if (has_arg)
++num_selectors_with_args;
- selector_idents.push_back (&m_ast->Idents.get (StringRef (start, len)));
+ selector_idents.push_back (&m_ast->Idents.get (llvm::StringRef (start, len)));
if (has_arg)
len += 1;
}
if (selector_idents.size() == 0)
- return 0;
+ return nullptr;
clang::Selector method_selector = m_ast->Selectors.getSelector (num_selectors_with_args ? selector_idents.size() : 0,
selector_idents.data());
- QualType method_qual_type (method_clang_type.GetQualType());
+ clang::QualType method_qual_type (method_clang_type.GetQualType());
// Populate the method decl with parameter decls
const clang::Type *method_type(method_qual_type.getTypePtr());
- if (method_type == NULL)
- return NULL;
+ if (method_type == nullptr)
+ return nullptr;
- const FunctionProtoType *method_function_prototype (dyn_cast<FunctionProtoType>(method_type));
+ const clang::FunctionProtoType *method_function_prototype (llvm::dyn_cast<clang::FunctionProtoType>(method_type));
if (!method_function_prototype)
- return NULL;
+ return nullptr;
bool is_variadic = false;
bool is_synthesized = false;
bool is_defined = false;
- ObjCMethodDecl::ImplementationControl imp_control = ObjCMethodDecl::None;
+ clang::ObjCMethodDecl::ImplementationControl imp_control = clang::ObjCMethodDecl::None;
const unsigned num_args = method_function_prototype->getNumParams();
if (num_args != num_selectors_with_args)
- return NULL; // some debug information is corrupt. We are not going to deal with it.
+ return nullptr; // some debug information is corrupt. We are not going to deal with it.
- ObjCMethodDecl *objc_method_decl = ObjCMethodDecl::Create (*m_ast,
- SourceLocation(), // beginLoc,
- SourceLocation(), // endLoc,
- method_selector,
- method_function_prototype->getReturnType(),
- NULL, // TypeSourceInfo *ResultTInfo,
- GetDeclContextForType (),
- name[0] == '-',
- is_variadic,
- is_synthesized,
- true, // is_implicitly_declared; we force this to true because we don't have source locations
- is_defined,
- imp_control,
- false /*has_related_result_type*/);
+ clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create (*m_ast,
+ clang::SourceLocation(), // beginLoc,
+ clang::SourceLocation(), // endLoc,
+ method_selector,
+ method_function_prototype->getReturnType(),
+ nullptr, // TypeSourceInfo *ResultTInfo,
+ GetDeclContextForType (),
+ name[0] == '-',
+ is_variadic,
+ is_synthesized,
+ true, // is_implicitly_declared; we force this to true because we don't have source locations
+ is_defined,
+ imp_control,
+ false /*has_related_result_type*/);
- if (objc_method_decl == NULL)
- return NULL;
+ if (objc_method_decl == nullptr)
+ return nullptr;
if (num_args > 0)
{
- llvm::SmallVector<ParmVarDecl *, 12> params;
+ llvm::SmallVector<clang::ParmVarDecl *, 12> params;
for (unsigned param_index = 0; param_index < num_args; ++param_index)
{
- params.push_back (ParmVarDecl::Create (*m_ast,
- objc_method_decl,
- SourceLocation(),
- SourceLocation(),
- NULL, // anonymous
- method_function_prototype->getParamType(param_index),
- NULL,
- SC_Auto,
- NULL));
+ params.push_back (clang::ParmVarDecl::Create (*m_ast,
+ objc_method_decl,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ nullptr, // anonymous
+ method_function_prototype->getParamType(param_index),
+ nullptr,
+ clang::SC_Auto,
+ nullptr));
}
- objc_method_decl->setMethodParams(*m_ast, ArrayRef<ParmVarDecl*>(params), ArrayRef<SourceLocation>());
+ objc_method_decl->setMethodParams(*m_ast, llvm::ArrayRef<clang::ParmVarDecl*>(params), llvm::ArrayRef<clang::SourceLocation>());
}
class_interface_decl->addDecl (objc_method_decl);
@@ -5192,9 +5368,9 @@ clang::DeclContext *
ClangASTType::GetDeclContextForType () const
{
if (!IsValid())
- return NULL;
+ return nullptr;
- QualType qual_type(GetCanonicalQualType());
+ clang::QualType qual_type(GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
@@ -5216,13 +5392,13 @@ ClangASTType::GetDeclContextForType () const
case clang::Type::MemberPointer: break;
case clang::Type::Complex: break;
case clang::Type::ObjCObject: break;
- case clang::Type::ObjCInterface: return cast<ObjCObjectType>(qual_type.getTypePtr())->getInterface();
- case clang::Type::ObjCObjectPointer: return ClangASTType (m_ast, cast<ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType()).GetDeclContextForType();
- case clang::Type::Record: return cast<RecordType>(qual_type)->getDecl();
- case clang::Type::Enum: return cast<EnumType>(qual_type)->getDecl();
- case clang::Type::Typedef: return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetDeclContextForType();
- case clang::Type::Elaborated: return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).GetDeclContextForType();
- case clang::Type::Paren: return ClangASTType (m_ast, cast<ParenType>(qual_type)->desugar()).GetDeclContextForType();
+ case clang::Type::ObjCInterface: return llvm::cast<clang::ObjCObjectType>(qual_type.getTypePtr())->getInterface();
+ case clang::Type::ObjCObjectPointer: return ClangASTType (m_ast, llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType()).GetDeclContextForType();
+ case clang::Type::Record: return llvm::cast<clang::RecordType>(qual_type)->getDecl();
+ case clang::Type::Enum: return llvm::cast<clang::EnumType>(qual_type)->getDecl();
+ case clang::Type::Typedef: return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetDeclContextForType();
+ case clang::Type::Elaborated: return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetDeclContextForType();
+ case clang::Type::Paren: return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetDeclContextForType();
case clang::Type::TypeOfExpr: break;
case clang::Type::TypeOf: break;
case clang::Type::Decltype: break;
@@ -5239,12 +5415,13 @@ ClangASTType::GetDeclContextForType () const
case clang::Type::InjectedClassName: break;
case clang::Type::DependentName: break;
case clang::Type::Atomic: break;
+ case clang::Type::Adjusted: break;
// pointer type decayed from an array or function type.
case clang::Type::Decayed: break;
}
// No DeclContext in this type...
- return NULL;
+ return nullptr;
}
bool
@@ -5254,18 +5431,18 @@ ClangASTType::SetDefaultAccessForRecordFields (int default_accessibility,
{
if (IsValid())
{
- RecordDecl *record_decl = GetAsRecordDecl();
+ clang::RecordDecl *record_decl = GetAsRecordDecl();
if (record_decl)
{
uint32_t field_idx;
- RecordDecl::field_iterator field, field_end;
+ clang::RecordDecl::field_iterator field, field_end;
for (field = record_decl->field_begin(), field_end = record_decl->field_end(), field_idx = 0;
field != field_end;
++field, ++field_idx)
{
// If no accessibility was assigned, assign the correct one
if (field_idx < num_assigned_accessibilities && assigned_accessibilities[field_idx] == clang::AS_none)
- field->setAccess ((AccessSpecifier)default_accessibility);
+ field->setAccess ((clang::AccessSpecifier)default_accessibility);
}
return true;
}
@@ -5280,14 +5457,14 @@ ClangASTType::SetHasExternalStorage (bool has_extern)
if (!IsValid())
return false;
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Record:
{
- CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
if (cxx_record_decl)
{
cxx_record_decl->setHasExternalLexicalStorage (has_extern);
@@ -5299,7 +5476,7 @@ ClangASTType::SetHasExternalStorage (bool has_extern)
case clang::Type::Enum:
{
- EnumDecl *enum_decl = cast<EnumType>(qual_type)->getDecl();
+ clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
if (enum_decl)
{
enum_decl->setHasExternalLexicalStorage (has_extern);
@@ -5312,11 +5489,11 @@ ClangASTType::SetHasExternalStorage (bool has_extern)
case clang::Type::ObjCObject:
case clang::Type::ObjCInterface:
{
- const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr());
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
assert (objc_class_type);
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
if (class_interface_decl)
{
@@ -5329,13 +5506,13 @@ ClangASTType::SetHasExternalStorage (bool has_extern)
break;
case clang::Type::Typedef:
- return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).SetHasExternalStorage (has_extern);
+ return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).SetHasExternalStorage (has_extern);
case clang::Type::Elaborated:
- return ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).SetHasExternalStorage (has_extern);
+ return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).SetHasExternalStorage (has_extern);
case clang::Type::Paren:
- return ClangASTType (m_ast, cast<ParenType>(qual_type)->desugar()).SetHasExternalStorage (has_extern);
+ return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).SetHasExternalStorage (has_extern);
default:
break;
@@ -5348,17 +5525,17 @@ ClangASTType::SetTagTypeKind (int kind) const
{
if (IsValid())
{
- QualType tag_qual_type(GetQualType());
+ clang::QualType tag_qual_type(GetQualType());
const clang::Type *clang_type = tag_qual_type.getTypePtr();
if (clang_type)
{
- const TagType *tag_type = dyn_cast<TagType>(clang_type);
+ const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(clang_type);
if (tag_type)
{
- TagDecl *tag_decl = dyn_cast<TagDecl>(tag_type->getDecl());
+ clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl());
if (tag_decl)
{
- tag_decl->setTagKind ((TagDecl::TagKind)kind);
+ tag_decl->setTagKind ((clang::TagDecl::TagKind)kind);
return true;
}
}
@@ -5375,14 +5552,14 @@ ClangASTType::StartTagDeclarationDefinition ()
{
if (IsValid())
{
- QualType qual_type (GetQualType());
+ clang::QualType qual_type (GetQualType());
const clang::Type *t = qual_type.getTypePtr();
if (t)
{
- const TagType *tag_type = dyn_cast<TagType>(t);
+ const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(t);
if (tag_type)
{
- TagDecl *tag_decl = tag_type->getDecl();
+ clang::TagDecl *tag_decl = tag_type->getDecl();
if (tag_decl)
{
tag_decl->startDefinition();
@@ -5390,10 +5567,10 @@ ClangASTType::StartTagDeclarationDefinition ()
}
}
- const ObjCObjectType *object_type = dyn_cast<ObjCObjectType>(t);
+ const clang::ObjCObjectType *object_type = llvm::dyn_cast<clang::ObjCObjectType>(t);
if (object_type)
{
- ObjCInterfaceDecl *interface_decl = object_type->getInterface();
+ clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface();
if (interface_decl)
{
interface_decl->startDefinition();
@@ -5410,9 +5587,9 @@ ClangASTType::CompleteTagDeclarationDefinition ()
{
if (IsValid())
{
- QualType qual_type (GetQualType());
+ clang::QualType qual_type (GetQualType());
- CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
if (cxx_record_decl)
{
@@ -5421,11 +5598,11 @@ ClangASTType::CompleteTagDeclarationDefinition ()
return true;
}
- const EnumType *enum_type = dyn_cast<EnumType>(qual_type.getTypePtr());
+ const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(qual_type.getTypePtr());
if (enum_type)
{
- EnumDecl *enum_decl = enum_type->getDecl();
+ clang::EnumDecl *enum_decl = enum_type->getDecl();
if (enum_decl)
{
@@ -5434,7 +5611,7 @@ ClangASTType::CompleteTagDeclarationDefinition ()
unsigned NumPositiveBits = 1;
unsigned NumNegativeBits = 0;
- QualType promotion_qual_type;
+ clang::QualType promotion_qual_type;
// If the enum integer type is less than an integer in bit width,
// then we must promote it to an integer size.
if (m_ast->getTypeSize(enum_decl->getIntegerType()) < m_ast->getTypeSize(m_ast->IntTy))
@@ -5470,27 +5647,27 @@ ClangASTType::AddEnumerationValueToEnumerationType (const ClangASTType &enumerat
{
if (IsValid() && enumerator_clang_type.IsValid() && name && name[0])
{
- QualType enum_qual_type (GetCanonicalQualType());
+ clang::QualType enum_qual_type (GetCanonicalQualType());
bool is_signed = false;
enumerator_clang_type.IsIntegerType (is_signed);
const clang::Type *clang_type = enum_qual_type.getTypePtr();
if (clang_type)
{
- const EnumType *enum_type = dyn_cast<EnumType>(clang_type);
+ const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(clang_type);
if (enum_type)
{
llvm::APSInt enum_llvm_apsint(enum_value_bit_size, is_signed);
enum_llvm_apsint = enum_value;
- EnumConstantDecl *enumerator_decl =
- EnumConstantDecl::Create (*m_ast,
- enum_type->getDecl(),
- SourceLocation(),
- name ? &m_ast->Idents.get(name) : NULL, // Identifier
- enumerator_clang_type.GetQualType(),
- NULL,
- enum_llvm_apsint);
+ clang::EnumConstantDecl *enumerator_decl =
+ clang::EnumConstantDecl::Create (*m_ast,
+ enum_type->getDecl(),
+ clang::SourceLocation(),
+ name ? &m_ast->Idents.get(name) : nullptr, // Identifier
+ enumerator_clang_type.GetQualType(),
+ nullptr,
+ enum_llvm_apsint);
if (enumerator_decl)
{
@@ -5512,14 +5689,14 @@ ClangASTType::AddEnumerationValueToEnumerationType (const ClangASTType &enumerat
ClangASTType
ClangASTType::GetEnumerationIntegerType () const
{
- QualType enum_qual_type (GetCanonicalQualType());
+ clang::QualType enum_qual_type (GetCanonicalQualType());
const clang::Type *clang_type = enum_qual_type.getTypePtr();
if (clang_type)
{
- const EnumType *enum_type = dyn_cast<EnumType>(clang_type);
+ const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(clang_type);
if (enum_type)
{
- EnumDecl *enum_decl = enum_type->getDecl();
+ clang::EnumDecl *enum_decl = enum_type->getDecl();
if (enum_decl)
return ClangASTType (m_ast, enum_decl->getIntegerType());
}
@@ -5544,7 +5721,7 @@ ClangASTType::ConvertStringToFloatValue (const char *s, uint8_t *dst, size_t dst
{
if (IsValid())
{
- QualType qual_type (GetCanonicalQualType());
+ clang::QualType qual_type (GetCanonicalQualType());
uint32_t count = 0;
bool is_complex = false;
if (IsFloatingPointType (count, is_complex))
@@ -5553,8 +5730,8 @@ ClangASTType::ConvertStringToFloatValue (const char *s, uint8_t *dst, size_t dst
if (count != 1)
return false;
- StringRef s_sref(s);
- APFloat ap_float(m_ast->getFloatTypeSemantics(qual_type), s_sref);
+ llvm::StringRef s_sref(s);
+ llvm::APFloat ap_float(m_ast->getFloatTypeSemantics(qual_type), s_sref);
const uint64_t bit_size = m_ast->getTypeSize (qual_type);
const uint64_t byte_size = bit_size / 8;
@@ -5602,30 +5779,30 @@ ClangASTType::DumpValue (ExecutionContext *exe_ctx,
if (!IsValid())
return;
- QualType qual_type(GetQualType());
+ clang::QualType qual_type(GetQualType());
switch (qual_type->getTypeClass())
{
case clang::Type::Record:
if (GetCompleteType ())
{
- const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
- const RecordDecl *record_decl = record_type->getDecl();
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
assert(record_decl);
uint32_t field_bit_offset = 0;
uint32_t field_byte_offset = 0;
- const ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(record_decl);
+ const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(record_decl);
uint32_t child_idx = 0;
- const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
if (cxx_record_decl)
{
// We might have base classes to print out first
- CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
base_class != base_class_end;
++base_class)
{
- const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+ const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
// Skip empty base classes
if (verbose == false && ClangASTContext::RecordHasFields(base_class_decl) == false)
@@ -5642,13 +5819,13 @@ ClangASTType::DumpValue (ExecutionContext *exe_ctx,
else
s->PutChar(',');
- QualType base_class_qual_type = base_class->getType();
+ clang::QualType base_class_qual_type = base_class->getType();
std::string base_class_type_name(base_class_qual_type.getAsString());
// Indent and print the base class type name
s->Printf("\n%*s%s ", depth + DEPTH_INCREMENT, "", base_class_type_name.c_str());
- std::pair<uint64_t, unsigned> base_class_type_info = m_ast->getTypeInfo(base_class_qual_type);
+ clang::TypeInfo base_class_type_info = m_ast->getTypeInfo(base_class_qual_type);
// Dump the value of the member
ClangASTType base_clang_type(m_ast, base_class_qual_type);
@@ -5657,7 +5834,7 @@ ClangASTType::DumpValue (ExecutionContext *exe_ctx,
base_clang_type.GetFormat(), // The format with which to display the member
data, // Data buffer containing all bytes for this type
data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from
- base_class_type_info.first / 8, // Size of this type in bytes
+ base_class_type_info.Width / 8, // Size of this type in bytes
0, // Bitfield bit size
0, // Bitfield bit offset
show_types, // Boolean indicating if we should show the variable types
@@ -5669,7 +5846,7 @@ ClangASTType::DumpValue (ExecutionContext *exe_ctx,
}
}
uint32_t field_idx = 0;
- RecordDecl::field_iterator field, field_end;
+ clang::RecordDecl::field_iterator field, field_end;
for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx)
{
// Print the starting squiggly bracket (if this is the
@@ -5683,11 +5860,11 @@ ClangASTType::DumpValue (ExecutionContext *exe_ctx,
// Indent
s->Printf("\n%*s", depth + DEPTH_INCREMENT, "");
- QualType field_type = field->getType();
+ clang::QualType field_type = field->getType();
// Print the member type if requested
// Figure out the type byte size (field_type_info.first) and
// alignment (field_type_info.second) from the AST context.
- std::pair<uint64_t, unsigned> field_type_info = m_ast->getTypeInfo(field_type);
+ clang::TypeInfo field_type_info = m_ast->getTypeInfo(field_type);
assert(field_idx < record_layout.getFieldCount());
// Figure out the field offset within the current struct/union/class type
field_bit_offset = record_layout.getFieldOffset (field_idx);
@@ -5716,7 +5893,7 @@ ClangASTType::DumpValue (ExecutionContext *exe_ctx,
field_clang_type.GetFormat(), // The format with which to display the member
data, // Data buffer containing all bytes for this type
data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from
- field_type_info.first / 8, // Size of this type in bytes
+ field_type_info.Width / 8, // Size of this type in bytes
field_bitfield_bit_size, // Bitfield bit size
field_bitfield_bit_offset, // Bitfield bit offset
show_types, // Boolean indicating if we should show the variable types
@@ -5734,10 +5911,10 @@ ClangASTType::DumpValue (ExecutionContext *exe_ctx,
case clang::Type::Enum:
if (GetCompleteType ())
{
- const EnumType *enum_type = cast<EnumType>(qual_type.getTypePtr());
- const EnumDecl *enum_decl = enum_type->getDecl();
+ const clang::EnumType *enum_type = llvm::cast<clang::EnumType>(qual_type.getTypePtr());
+ const clang::EnumDecl *enum_decl = enum_type->getDecl();
assert(enum_decl);
- EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
+ clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
lldb::offset_t offset = data_byte_offset;
const int64_t enum_value = data.GetMaxU64Bitfield(&offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset);
for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
@@ -5756,9 +5933,9 @@ ClangASTType::DumpValue (ExecutionContext *exe_ctx,
case clang::Type::ConstantArray:
{
- const ConstantArrayType *array = cast<ConstantArrayType>(qual_type.getTypePtr());
+ const clang::ConstantArrayType *array = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr());
bool is_array_of_characters = false;
- QualType element_qual_type = array->getElementType();
+ clang::QualType element_qual_type = array->getElementType();
const clang::Type *canonical_type = element_qual_type->getCanonicalTypeInternal().getTypePtr();
if (canonical_type)
@@ -5766,11 +5943,11 @@ ClangASTType::DumpValue (ExecutionContext *exe_ctx,
const uint64_t element_count = array->getSize().getLimitedValue();
- std::pair<uint64_t, unsigned> field_type_info = m_ast->getTypeInfo(element_qual_type);
+ clang::TypeInfo field_type_info = m_ast->getTypeInfo(element_qual_type);
uint32_t element_idx = 0;
uint32_t element_offset = 0;
- uint64_t element_byte_size = field_type_info.first / 8;
+ uint64_t element_byte_size = field_type_info.Width / 8;
uint32_t element_stride = element_byte_size;
if (is_array_of_characters)
@@ -5825,12 +6002,12 @@ ClangASTType::DumpValue (ExecutionContext *exe_ctx,
case clang::Type::Typedef:
{
- QualType typedef_qual_type = cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType();
+ clang::QualType typedef_qual_type = llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType();
ClangASTType typedef_clang_type (m_ast, typedef_qual_type);
lldb::Format typedef_format = typedef_clang_type.GetFormat();
- std::pair<uint64_t, unsigned> typedef_type_info = m_ast->getTypeInfo(typedef_qual_type);
- uint64_t typedef_byte_size = typedef_type_info.first / 8;
+ clang::TypeInfo typedef_type_info = m_ast->getTypeInfo(typedef_qual_type);
+ uint64_t typedef_byte_size = typedef_type_info.Width / 8;
return typedef_clang_type.DumpValue (exe_ctx,
s, // Stream to dump to
@@ -5849,11 +6026,11 @@ ClangASTType::DumpValue (ExecutionContext *exe_ctx,
case clang::Type::Elaborated:
{
- QualType elaborated_qual_type = cast<ElaboratedType>(qual_type)->getNamedType();
+ clang::QualType elaborated_qual_type = llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType();
ClangASTType elaborated_clang_type (m_ast, elaborated_qual_type);
lldb::Format elaborated_format = elaborated_clang_type.GetFormat();
- std::pair<uint64_t, unsigned> elaborated_type_info = m_ast->getTypeInfo(elaborated_qual_type);
- uint64_t elaborated_byte_size = elaborated_type_info.first / 8;
+ clang::TypeInfo elaborated_type_info = m_ast->getTypeInfo(elaborated_qual_type);
+ uint64_t elaborated_byte_size = elaborated_type_info.Width / 8;
return elaborated_clang_type.DumpValue (exe_ctx,
s, // Stream to dump to
@@ -5872,12 +6049,12 @@ ClangASTType::DumpValue (ExecutionContext *exe_ctx,
case clang::Type::Paren:
{
- QualType desugar_qual_type = cast<ParenType>(qual_type)->desugar();
+ clang::QualType desugar_qual_type = llvm::cast<clang::ParenType>(qual_type)->desugar();
ClangASTType desugar_clang_type (m_ast, desugar_qual_type);
lldb::Format desugar_format = desugar_clang_type.GetFormat();
- std::pair<uint64_t, unsigned> desugar_type_info = m_ast->getTypeInfo(desugar_qual_type);
- uint64_t desugar_byte_size = desugar_type_info.first / 8;
+ clang::TypeInfo desugar_type_info = m_ast->getTypeInfo(desugar_qual_type);
+ uint64_t desugar_byte_size = desugar_type_info.Width / 8;
return desugar_clang_type.DumpValue (exe_ctx,
s, // Stream to dump to
@@ -5933,19 +6110,19 @@ ClangASTType::DumpTypeValue (Stream *s,
}
else
{
- QualType qual_type(GetQualType());
+ clang::QualType qual_type(GetQualType());
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
{
case clang::Type::Typedef:
{
- QualType typedef_qual_type = cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType();
+ clang::QualType typedef_qual_type = llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType();
ClangASTType typedef_clang_type (m_ast, typedef_qual_type);
if (format == eFormatDefault)
format = typedef_clang_type.GetFormat();
- std::pair<uint64_t, unsigned> typedef_type_info = m_ast->getTypeInfo(typedef_qual_type);
- uint64_t typedef_byte_size = typedef_type_info.first / 8;
+ clang::TypeInfo typedef_type_info = m_ast->getTypeInfo(typedef_qual_type);
+ uint64_t typedef_byte_size = typedef_type_info.Width / 8;
return typedef_clang_type.DumpTypeValue (s,
format, // The format with which to display the element
@@ -5963,10 +6140,10 @@ ClangASTType::DumpTypeValue (Stream *s,
// its enumeration string value, else just display it as requested.
if ((format == eFormatEnum || format == eFormatDefault) && GetCompleteType ())
{
- const EnumType *enum_type = cast<EnumType>(qual_type.getTypePtr());
- const EnumDecl *enum_decl = enum_type->getDecl();
+ const clang::EnumType *enum_type = llvm::cast<clang::EnumType>(qual_type.getTypePtr());
+ const clang::EnumDecl *enum_decl = enum_type->getDecl();
assert(enum_decl);
- EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
+ clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
const bool is_signed = qual_type->isSignedIntegerOrEnumerationType();
lldb::offset_t offset = byte_offset;
if (is_signed)
@@ -6093,7 +6270,7 @@ ClangASTType::DumpSummary (ExecutionContext *exe_ctx,
if (process)
{
lldb::offset_t offset = data_byte_offset;
- lldb::addr_t pointer_addresss = data.GetMaxU64(&offset, data_byte_size);
+ lldb::addr_t pointer_address = data.GetMaxU64(&offset, data_byte_size);
std::vector<uint8_t> buf;
if (length > 0)
buf.resize (length);
@@ -6105,7 +6282,7 @@ ClangASTType::DumpSummary (ExecutionContext *exe_ctx,
size_t bytes_read;
size_t total_cstr_len = 0;
Error error;
- while ((bytes_read = process->ReadMemory (pointer_addresss, &buf.front(), buf.size(), error)) > 0)
+ while ((bytes_read = process->ReadMemory (pointer_address, &buf.front(), buf.size(), error)) > 0)
{
const size_t len = strlen((const char *)&buf.front());
if (len == 0)
@@ -6116,7 +6293,7 @@ ClangASTType::DumpSummary (ExecutionContext *exe_ctx,
total_cstr_len += len;
if (len < buf.size())
break;
- pointer_addresss += total_cstr_len;
+ pointer_address += total_cstr_len;
}
if (total_cstr_len > 0)
s->PutChar ('"');
@@ -6142,10 +6319,10 @@ ClangASTType::DumpTypeDescription (Stream *s) const
{
if (IsValid())
{
- QualType qual_type(GetQualType());
+ clang::QualType qual_type(GetQualType());
- SmallVector<char, 1024> buf;
- raw_svector_ostream llvm_ostrm (buf);
+ llvm::SmallVector<char, 1024> buf;
+ llvm::raw_svector_ostream llvm_ostrm (buf);
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
switch (type_class)
@@ -6155,14 +6332,14 @@ ClangASTType::DumpTypeDescription (Stream *s) const
{
GetCompleteType ();
- const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr());
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
assert (objc_class_type);
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
if (class_interface_decl)
{
- PrintingPolicy policy = m_ast->getPrintingPolicy();
+ clang::PrintingPolicy policy = m_ast->getPrintingPolicy();
class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel());
}
}
@@ -6171,10 +6348,10 @@ ClangASTType::DumpTypeDescription (Stream *s) const
case clang::Type::Typedef:
{
- const TypedefType *typedef_type = qual_type->getAs<TypedefType>();
+ const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
if (typedef_type)
{
- const TypedefNameDecl *typedef_decl = typedef_type->getDecl();
+ const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
std::string clang_typedef_name (typedef_decl->getQualifiedNameAsString());
if (!clang_typedef_name.empty())
{
@@ -6186,20 +6363,20 @@ ClangASTType::DumpTypeDescription (Stream *s) const
break;
case clang::Type::Elaborated:
- ClangASTType (m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).DumpTypeDescription(s);
+ ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).DumpTypeDescription(s);
return;
case clang::Type::Paren:
- ClangASTType (m_ast, cast<ParenType>(qual_type)->desugar()).DumpTypeDescription(s);
+ ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).DumpTypeDescription(s);
return;
case clang::Type::Record:
{
GetCompleteType ();
- const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
- const RecordDecl *record_decl = record_type->getDecl();
- const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
if (cxx_record_decl)
cxx_record_decl->print(llvm_ostrm, m_ast->getPrintingPolicy(), s->GetIndentLevel());
@@ -6210,10 +6387,10 @@ ClangASTType::DumpTypeDescription (Stream *s) const
default:
{
- const TagType *tag_type = dyn_cast<TagType>(qual_type.getTypePtr());
+ const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
if (tag_type)
{
- TagDecl *tag_decl = tag_type->getDecl();
+ clang::TagDecl *tag_decl = tag_type->getDecl();
if (tag_decl)
tag_decl->print(llvm_ostrm, 0);
}
@@ -6471,19 +6648,19 @@ ClangASTType::ReadFromMemory (lldb_private::ExecutionContext *exe_ctx,
}
uint8_t* dst = (uint8_t*)data.PeekData(0, byte_size);
- if (dst != NULL)
+ if (dst != nullptr)
{
if (address_type == eAddressTypeHost)
{
if (addr == 0)
return false;
// The address is an address in this process, so just copy it
- memcpy (dst, (uint8_t*)NULL + addr, byte_size);
+ memcpy (dst, (uint8_t*)nullptr + addr, byte_size);
return true;
}
else
{
- Process *process = NULL;
+ Process *process = nullptr;
if (exe_ctx)
process = exe_ctx->GetProcessPtr();
if (process)
@@ -6525,7 +6702,7 @@ ClangASTType::WriteToMemory (lldb_private::ExecutionContext *exe_ctx,
}
else
{
- Process *process = NULL;
+ Process *process = nullptr;
if (exe_ctx)
process = exe_ctx->GetProcessPtr();
if (process)
@@ -6539,11 +6716,11 @@ ClangASTType::WriteToMemory (lldb_private::ExecutionContext *exe_ctx,
}
-//CXXRecordDecl *
+//clang::CXXRecordDecl *
//ClangASTType::GetAsCXXRecordDecl (lldb::clang_type_t opaque_clang_qual_type)
//{
// if (opaque_clang_qual_type)
-// return QualType::getFromOpaquePtr(opaque_clang_qual_type)->getAsCXXRecordDecl();
+// return clang::QualType::getFromOpaquePtr(opaque_clang_qual_type)->getAsCXXRecordDecl();
// return NULL;
//}
@@ -6561,3 +6738,4 @@ lldb_private::operator != (const lldb_private::ClangASTType &lhs, const lldb_pri
}
+
diff --git a/source/Symbol/ClangExternalASTSourceCallbacks.cpp b/source/Symbol/ClangExternalASTSourceCallbacks.cpp
index b2328d6e5b42..bdc32654cc10 100644
--- a/source/Symbol/ClangExternalASTSourceCallbacks.cpp
+++ b/source/Symbol/ClangExternalASTSourceCallbacks.cpp
@@ -14,7 +14,7 @@
// Other libraries and framework includes
// Clang headers like to use NDEBUG inside of them to enable/disable debug
-// releated features using "#ifndef NDEBUG" preprocessor blocks to do one thing
+// related features using "#ifndef NDEBUG" preprocessor blocks to do one thing
// or another. This is bad because it means that if clang was built in release
// mode, it assumes that you are building in release mode which is not always
// the case. You can end up with functions that are defined as empty in header
diff --git a/source/Symbol/ClangExternalASTSourceCommon.cpp b/source/Symbol/ClangExternalASTSourceCommon.cpp
index 697dc7eec493..650d252a8fc3 100644
--- a/source/Symbol/ClangExternalASTSourceCommon.cpp
+++ b/source/Symbol/ClangExternalASTSourceCommon.cpp
@@ -36,7 +36,7 @@ ClangExternalASTSourceCommon::GetMetadata (const void *object)
if (HasMetadata (object))
return &m_metadata[object];
else
- return NULL;
+ return nullptr;
}
void
diff --git a/source/Symbol/CompileUnit.cpp b/source/Symbol/CompileUnit.cpp
index 62ae1cc1cbe0..f99ca53d9629 100644
--- a/source/Symbol/CompileUnit.cpp
+++ b/source/Symbol/CompileUnit.cpp
@@ -99,11 +99,11 @@ CompileUnit::GetDescription(Stream *s, lldb::DescriptionLevel level) const
void
CompileUnit::Dump(Stream *s, bool show_context) const
{
- s->Printf("%p: ", this);
+ s->Printf("%p: ", static_cast<const void*>(this));
s->Indent();
- *s << "CompileUnit" << (const UserID&)*this
- << ", language = \"" << (const Language&)*this
- << "\", file = '" << (const FileSpec&)*this << "'\n";
+ *s << "CompileUnit" << static_cast<const UserID&>(*this)
+ << ", language = \"" << reinterpret_cast<const Language&>(*this)
+ << "\", file = '" << static_cast<const FileSpec&>(*this) << "'\n";
// m_types.Dump(s);
@@ -237,7 +237,7 @@ CompileUnit::GetLanguage()
LineTable*
CompileUnit::GetLineTable()
{
- if (m_line_table_ap.get() == NULL)
+ if (m_line_table_ap.get() == nullptr)
{
if (m_flags.IsClear(flagsParsedLineTable))
{
@@ -257,7 +257,7 @@ CompileUnit::GetLineTable()
void
CompileUnit::SetLineTable(LineTable* line_table)
{
- if (line_table == NULL)
+ if (line_table == nullptr)
m_flags.Clear(flagsParsedLineTable);
else
m_flags.Set(flagsParsedLineTable);
@@ -267,7 +267,7 @@ CompileUnit::SetLineTable(LineTable* line_table)
VariableListSP
CompileUnit::GetVariableList(bool can_create)
{
- if (m_variables.get() == NULL && can_create)
+ if (m_variables.get() == nullptr && can_create)
{
SymbolContext sc;
CalculateSymbolContext(&sc);
@@ -353,7 +353,7 @@ CompileUnit::ResolveSymbolContext
{
LineTable *line_table = sc.comp_unit->GetLineTable();
- if (line_table != NULL)
+ if (line_table != nullptr)
{
uint32_t found_line;
uint32_t line_idx;
diff --git a/source/Symbol/DWARFCallFrameInfo.cpp b/source/Symbol/DWARFCallFrameInfo.cpp
index d3d962896694..a9da631eb452 100644
--- a/source/Symbol/DWARFCallFrameInfo.cpp
+++ b/source/Symbol/DWARFCallFrameInfo.cpp
@@ -55,7 +55,7 @@ DWARFCallFrameInfo::GetUnwindPlan (Address addr, UnwindPlan& unwind_plan)
// Make sure that the Address we're searching for is the same object file
// as this DWARFCallFrameInfo, we only store File offsets in m_fde_index.
ModuleSP module_sp = addr.GetModule();
- if (module_sp.get() == NULL || module_sp->GetObjectFile() == NULL || module_sp->GetObjectFile() != &m_objfile)
+ if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr || module_sp->GetObjectFile() != &m_objfile)
return false;
if (GetFDEEntryByFileAddress (addr.GetFileAddress(), fde_entry) == false)
@@ -70,10 +70,10 @@ DWARFCallFrameInfo::GetAddressRange (Address addr, AddressRange &range)
// Make sure that the Address we're searching for is the same object file
// as this DWARFCallFrameInfo, we only store File offsets in m_fde_index.
ModuleSP module_sp = addr.GetModule();
- if (module_sp.get() == NULL || module_sp->GetObjectFile() == NULL || module_sp->GetObjectFile() != &m_objfile)
+ if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr || module_sp->GetObjectFile() != &m_objfile)
return false;
- if (m_section_sp.get() == NULL || m_section_sp->IsEncrypted())
+ if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
return false;
GetFDEIndex();
FDEEntryMap::Entry *fde_entry = m_fde_index.FindEntryThatContains (addr.GetFileAddress());
@@ -87,7 +87,7 @@ DWARFCallFrameInfo::GetAddressRange (Address addr, AddressRange &range)
bool
DWARFCallFrameInfo::GetFDEEntryByFileAddress (addr_t file_addr, FDEEntryMap::Entry &fde_entry)
{
- if (m_section_sp.get() == NULL || m_section_sp->IsEncrypted())
+ if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
return false;
GetFDEIndex();
@@ -97,7 +97,7 @@ DWARFCallFrameInfo::GetFDEEntryByFileAddress (addr_t file_addr, FDEEntryMap::Ent
FDEEntryMap::Entry *fde = m_fde_index.FindEntryThatContains (file_addr);
- if (fde == NULL)
+ if (fde == nullptr)
return false;
fde_entry = *fde;
@@ -131,12 +131,12 @@ DWARFCallFrameInfo::GetCIE(dw_offset_t cie_offset)
if (pos != m_cie_map.end())
{
// Parse and cache the CIE
- if (pos->second.get() == NULL)
+ if (pos->second.get() == nullptr)
pos->second = ParseCIE (cie_offset);
return pos->second.get();
}
- return NULL;
+ return nullptr;
}
DWARFCallFrameInfo::CIESP
@@ -146,9 +146,17 @@ DWARFCallFrameInfo::ParseCIE (const dw_offset_t cie_offset)
lldb::offset_t offset = cie_offset;
if (m_cfi_data_initialized == false)
GetCFIData();
- const uint32_t length = m_cfi_data.GetU32(&offset);
- const dw_offset_t cie_id = m_cfi_data.GetU32(&offset);
- const dw_offset_t end_offset = cie_offset + length + 4;
+ uint32_t length = m_cfi_data.GetU32(&offset);
+ dw_offset_t cie_id, end_offset;
+ bool is_64bit = (length == UINT32_MAX);
+ if (is_64bit) {
+ length = m_cfi_data.GetU64(&offset);
+ cie_id = m_cfi_data.GetU64(&offset);
+ end_offset = cie_offset + length + 12;
+ } else {
+ cie_id = m_cfi_data.GetU32(&offset);
+ end_offset = cie_offset + length + 4;
+ }
if (length > 0 && ((!m_is_eh_frame && cie_id == UINT32_MAX) || (m_is_eh_frame && cie_id == 0ul)))
{
size_t i;
@@ -318,7 +326,7 @@ DWARFCallFrameInfo::GetCFIData()
void
DWARFCallFrameInfo::GetFDEIndex ()
{
- if (m_section_sp.get() == NULL || m_section_sp->IsEncrypted())
+ if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
return;
if (m_fde_index_initialized)
@@ -337,9 +345,19 @@ DWARFCallFrameInfo::GetFDEIndex ()
while (m_cfi_data.ValidOffsetForDataOfSize (offset, 8))
{
const dw_offset_t current_entry = offset;
+ dw_offset_t cie_id, next_entry, cie_offset;
uint32_t len = m_cfi_data.GetU32 (&offset);
- dw_offset_t next_entry = current_entry + len + 4;
- dw_offset_t cie_id = m_cfi_data.GetU32 (&offset);
+ bool is_64bit = (len == UINT32_MAX);
+ if (is_64bit) {
+ len = m_cfi_data.GetU64 (&offset);
+ cie_id = m_cfi_data.GetU64 (&offset);
+ next_entry = current_entry + len + 12;
+ cie_offset = current_entry + 12 - cie_id;
+ } else {
+ cie_id = m_cfi_data.GetU32 (&offset);
+ next_entry = current_entry + len + 4;
+ cie_offset = current_entry + 4 - cie_id;
+ }
if (cie_id == 0 || cie_id == UINT32_MAX || len == 0)
{
@@ -348,7 +366,6 @@ DWARFCallFrameInfo::GetFDEIndex ()
continue;
}
- const dw_offset_t cie_offset = current_entry + 4 - cie_id;
const CIE *cie = GetCIE (cie_offset);
if (cie)
{
@@ -381,14 +398,21 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
lldb::offset_t offset = dwarf_offset;
lldb::offset_t current_entry = offset;
- if (m_section_sp.get() == NULL || m_section_sp->IsEncrypted())
+ if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
return false;
if (m_cfi_data_initialized == false)
GetCFIData();
uint32_t length = m_cfi_data.GetU32 (&offset);
- dw_offset_t cie_offset = m_cfi_data.GetU32 (&offset);
+ dw_offset_t cie_offset;
+ bool is_64bit = (length == UINT32_MAX);
+ if (is_64bit) {
+ length = m_cfi_data.GetU64 (&offset);
+ cie_offset = m_cfi_data.GetU64 (&offset);
+ } else {
+ cie_offset = m_cfi_data.GetU32 (&offset);
+ }
assert (cie_offset != 0 && cie_offset != UINT32_MAX);
@@ -398,7 +422,7 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
if (m_is_eh_frame)
{
unwind_plan.SetSourceName ("eh_frame CFI");
- cie_offset = current_entry + 4 - cie_offset;
+ cie_offset = current_entry + (is_64bit ? 12 : 4) - cie_offset;
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
}
else
@@ -413,9 +437,9 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
const CIE *cie = GetCIE (cie_offset);
- assert (cie != NULL);
+ assert (cie != nullptr);
- const dw_offset_t end_offset = current_entry + length + 4;
+ const dw_offset_t end_offset = current_entry + length + (is_64bit ? 12 : 4);
const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
diff --git a/source/Symbol/FuncUnwinders.cpp b/source/Symbol/FuncUnwinders.cpp
index 134dbf5f50db..95fc81747859 100644
--- a/source/Symbol/FuncUnwinders.cpp
+++ b/source/Symbol/FuncUnwinders.cpp
@@ -28,13 +28,11 @@ using namespace lldb_private;
FuncUnwinders::FuncUnwinders
(
UnwindTable& unwind_table,
- const lldb::UnwindAssemblySP& assembly_profiler,
AddressRange range
) :
m_unwind_table(unwind_table),
- m_assembly_profiler(assembly_profiler),
m_range(range),
- m_mutex (Mutex::eMutexTypeNormal),
+ m_mutex (Mutex::eMutexTypeRecursive),
m_unwind_plan_call_site_sp (),
m_unwind_plan_non_call_site_sp (),
m_unwind_plan_fast_sp (),
@@ -68,7 +66,7 @@ FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
// 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() == NULL)
+ if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_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
@@ -96,7 +94,7 @@ FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
}
UnwindPlanSP
-FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread)
+FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, 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
@@ -111,13 +109,29 @@ FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread)
// 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() == NULL)
+ if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == nullptr)
{
- m_tried_unwind_at_non_call_site = true;
- if (m_assembly_profiler)
+ UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler());
+ if (assembly_profiler_sp)
{
+ 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)
+ {
+ // 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_non_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
- if (!m_assembly_profiler->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_non_call_site_sp))
+ if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_non_call_site_sp))
m_unwind_plan_non_call_site_sp.reset();
}
}
@@ -140,13 +154,14 @@ FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
// if (best_unwind_plan == NULL)
// best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
Mutex::Locker locker (m_mutex);
- if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == NULL)
+ if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == nullptr)
{
m_tried_unwind_fast = true;
- if (m_assembly_profiler)
+ UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler());
+ if (assembly_profiler_sp)
{
m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
- if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp))
+ if (!assembly_profiler_sp->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp))
m_unwind_plan_fast_sp.reset();
}
}
@@ -169,7 +184,7 @@ FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
// if (best_unwind_plan == NULL)
// best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
Mutex::Locker locker (m_mutex);
- if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == NULL)
+ if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == nullptr)
{
m_tried_unwind_arch_default = true;
Address current_pc;
@@ -205,7 +220,7 @@ FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread)
// if (best_unwind_plan == NULL)
// best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
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() == NULL)
+ 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;
@@ -232,8 +247,10 @@ FuncUnwinders::GetFirstNonPrologueInsn (Target& target)
if (m_first_non_prologue_insn.IsValid())
return m_first_non_prologue_insn;
ExecutionContext exe_ctx (target.shared_from_this(), false);
- if (m_assembly_profiler)
- m_assembly_profiler->FirstNonPrologueInsn (m_range, exe_ctx, m_first_non_prologue_insn);
+ 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;
}
@@ -252,3 +269,15 @@ FuncUnwinders::InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& thread)
m_unwind_plan_call_site_sp = arch_default;
}
}
+
+lldb::UnwindAssemblySP
+FuncUnwinders::GetUnwindAssemblyProfiler ()
+{
+ UnwindAssemblySP assembly_profiler_sp;
+ ArchSpec arch;
+ if (m_unwind_table.GetArchitecture (arch))
+ {
+ assembly_profiler_sp = UnwindAssembly::FindPlugin (arch);
+ }
+ return assembly_profiler_sp;
+}
diff --git a/source/Symbol/Function.cpp b/source/Symbol/Function.cpp
index e6d6c000bc97..0b7430ad75e3 100644
--- a/source/Symbol/Function.cpp
+++ b/source/Symbol/Function.cpp
@@ -215,7 +215,7 @@ Function::Function
m_prologue_byte_size (0)
{
m_block.SetParentScope(this);
- assert(comp_unit != NULL);
+ assert(comp_unit != nullptr);
}
Function::Function
@@ -239,7 +239,7 @@ Function::Function
m_prologue_byte_size (0)
{
m_block.SetParentScope(this);
- assert(comp_unit != NULL);
+ assert(comp_unit != nullptr);
}
@@ -253,10 +253,10 @@ Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
line_no = 0;
source_file.Clear();
- if (m_comp_unit == NULL)
+ if (m_comp_unit == nullptr)
return;
- if (m_type != NULL && m_type->GetDeclaration().GetLine() != 0)
+ if (m_type != nullptr && m_type->GetDeclaration().GetLine() != 0)
{
source_file = m_type->GetDeclaration().GetFile();
line_no = m_type->GetDeclaration().GetLine();
@@ -264,11 +264,11 @@ Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
else
{
LineTable *line_table = m_comp_unit->GetLineTable();
- if (line_table == NULL)
+ if (line_table == nullptr)
return;
LineEntry line_entry;
- if (line_table->FindLineEntryByAddress (GetAddressRange().GetBaseAddress(), line_entry, NULL))
+ if (line_table->FindLineEntryByAddress (GetAddressRange().GetBaseAddress(), line_entry, nullptr))
{
line_no = line_entry.line;
source_file = line_entry.file;
@@ -288,11 +288,11 @@ Function::GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
scratch_addr.SetOffset (scratch_addr.GetOffset() + GetAddressRange().GetByteSize() - 1);
LineTable *line_table = m_comp_unit->GetLineTable();
- if (line_table == NULL)
+ if (line_table == nullptr)
return;
LineEntry line_entry;
- if (line_table->FindLineEntryByAddress (scratch_addr, line_entry, NULL))
+ if (line_table->FindLineEntryByAddress (scratch_addr, line_entry, nullptr))
{
line_no = line_entry.line;
source_file = line_entry.file;
@@ -354,20 +354,16 @@ Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target
void
Function::Dump(Stream *s, bool show_context) const
{
- s->Printf("%p: ", this);
+ s->Printf("%p: ", static_cast<const void*>(this));
s->Indent();
- *s << "Function" << (const UserID&)*this;
+ *s << "Function" << static_cast<const UserID&>(*this);
m_mangled.Dump(s);
if (m_type)
- {
- s->Printf(", type = %p", m_type);
- }
+ s->Printf(", type = %p", static_cast<void*>(m_type));
else if (m_type_uid != LLDB_INVALID_UID)
- {
s->Printf(", type_uid = 0x%8.8" PRIx64, m_type_uid);
- }
s->EOL();
// Dump the root object
@@ -415,7 +411,7 @@ Function::GetInstructions (const ExecutionContext &exe_ctx,
{
const bool prefer_file_cache = false;
return Disassembler::DisassembleRange (module_sp->GetArchitecture(),
- NULL,
+ nullptr,
flavor,
exe_ctx,
GetAddressRange(),
@@ -471,17 +467,17 @@ Function::GetClangDeclContext()
CalculateSymbolContext (&sc);
if (!sc.module_sp)
- return NULL;
+ return nullptr;
SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
if (!sym_vendor)
- return NULL;
+ return nullptr;
SymbolFile *sym_file = sym_vendor->GetSymbolFile();
if (!sym_file)
- return NULL;
+ return nullptr;
return sym_file->GetClangDeclContextForTypeUID (sc, m_uid);
}
@@ -489,24 +485,24 @@ Function::GetClangDeclContext()
Type*
Function::GetType()
{
- if (m_type == NULL)
+ if (m_type == nullptr)
{
SymbolContext sc;
CalculateSymbolContext (&sc);
if (!sc.module_sp)
- return NULL;
+ return nullptr;
SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
- if (sym_vendor == NULL)
- return NULL;
+ if (sym_vendor == nullptr)
+ return nullptr;
SymbolFile *sym_file = sym_vendor->GetSymbolFile();
- if (sym_file == NULL)
- return NULL;
+ if (sym_file == nullptr)
+ return nullptr;
m_type = sym_file->ResolveTypeUID(m_type_uid);
}
diff --git a/source/Symbol/LineTable.cpp b/source/Symbol/LineTable.cpp
index a4aa35ddb318..4b4e33b2b0e9 100644
--- a/source/Symbol/LineTable.cpp
+++ b/source/Symbol/LineTable.cpp
@@ -93,16 +93,26 @@ LineTable::AppendLineEntryToSequence
bool is_terminal_entry
)
{
- assert(sequence != NULL);
+ assert(sequence != nullptr);
LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence);
Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);
- seq->m_entries.push_back (entry);
+ entry_collection &entries = seq->m_entries;
+ // Replace the last entry if the address is the same, otherwise append it. If we have multiple
+ // line entries at the same address, this indicates illegal DWARF so this "fixes" the line table
+ // to be correct. If not fixed this can cause a line entry's address that when resolved back to
+ // a symbol context, could resolve to a different line entry. We really want a 1 to 1 mapping
+ // here to avoid these kinds of inconsistencies. We will need tor revisit this if the DWARF line
+ // tables are updated to allow multiple entries at the same address legally.
+ if (!entries.empty() && entries.back().file_addr == file_addr)
+ entries.back() = entry;
+ else
+ entries.push_back (entry);
}
void
LineTable::InsertSequence (LineSequence* sequence)
{
- assert(sequence != NULL);
+ assert(sequence != nullptr);
LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence);
if (seq->m_entries.empty())
return;
@@ -183,7 +193,7 @@ LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry& line_entry)
bool
LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr)
{
- if (index_ptr != NULL )
+ if (index_ptr != nullptr )
*index_ptr = UINT32_MAX;
bool success = false;
@@ -247,7 +257,7 @@ LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry
{
uint32_t match_idx = std::distance (begin_pos, pos);
success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry);
- if (index_ptr != NULL && success)
+ if (index_ptr != nullptr && success)
*index_ptr = match_idx;
}
}
@@ -493,8 +503,8 @@ LineTable::LinkLineTable (const FileRangeMap &file_range_map)
LineSequenceImpl sequence;
const size_t count = m_entries.size();
LineEntry line_entry;
- const FileRangeMap::Entry *file_range_entry = NULL;
- const FileRangeMap::Entry *prev_file_range_entry = NULL;
+ const FileRangeMap::Entry *file_range_entry = nullptr;
+ const FileRangeMap::Entry *prev_file_range_entry = nullptr;
lldb::addr_t prev_file_addr = LLDB_INVALID_ADDRESS;
bool prev_entry_was_linked = false;
bool range_changed = false;
@@ -504,7 +514,7 @@ LineTable::LinkLineTable (const FileRangeMap &file_range_map)
const bool end_sequence = entry.is_terminal_entry;
const lldb::addr_t lookup_file_addr = entry.file_addr - (end_sequence ? 1 : 0);
- if (file_range_entry == NULL || !file_range_entry->Contains(lookup_file_addr))
+ if (file_range_entry == nullptr || !file_range_entry->Contains(lookup_file_addr))
{
prev_file_range_entry = file_range_entry;
file_range_entry = file_range_map.FindEntryThatContains(lookup_file_addr);
@@ -573,13 +583,13 @@ LineTable::LinkLineTable (const FileRangeMap &file_range_map)
}
else
{
- prev_entry_was_linked = file_range_entry != NULL;
+ prev_entry_was_linked = file_range_entry != nullptr;
}
prev_file_addr = entry.file_addr;
range_changed = false;
}
if (line_table_ap->m_entries.empty())
- return NULL;
+ return nullptr;
return line_table_ap.release();
}
diff --git a/source/Symbol/ObjectFile.cpp b/source/Symbol/ObjectFile.cpp
index ec69c9dd1e15..11b540071208 100644
--- a/source/Symbol/ObjectFile.cpp
+++ b/source/Symbol/ObjectFile.cpp
@@ -42,7 +42,9 @@ ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp,
Timer scoped_timer (__PRETTY_FUNCTION__,
"ObjectFile::FindPlugin (module = %s, file = %p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")",
module_sp->GetFileSpec().GetPath().c_str(),
- file, (uint64_t) file_offset, (uint64_t) file_size);
+ static_cast<const void*>(file),
+ static_cast<uint64_t>(file_offset),
+ static_cast<uint64_t>(file_size));
if (file)
{
FileSpec archive_file;
@@ -57,13 +59,13 @@ ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp,
// first
if (file_exists && module_sp->GetObjectName())
{
- for (uint32_t idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != NULL; ++idx)
+ for (uint32_t idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != nullptr; ++idx)
{
std::unique_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module_sp, data_sp, data_offset, file, file_offset, file_size));
-
+
if (object_container_ap.get())
object_file_sp = object_container_ap->GetObjectFile(file);
-
+
if (object_file_sp.get())
return object_file_sp;
}
@@ -99,13 +101,13 @@ ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp,
// from the container plugins since we had a name. Also, don't read
// ANY data in case there is data cached in the container plug-ins
// (like BSD archives caching the contained objects within an file).
- for (uint32_t idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != NULL; ++idx)
+ for (uint32_t idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != nullptr; ++idx)
{
std::unique_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module_sp, data_sp, data_offset, file, file_offset, file_size));
-
+
if (object_container_ap.get())
object_file_sp = object_container_ap->GetObjectFile(file);
-
+
if (object_file_sp.get())
return object_file_sp;
}
@@ -121,7 +123,7 @@ ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp,
// Check if this is a normal object file by iterating through
// all object file plugin instances.
ObjectFileCreateInstance create_object_file_callback;
- for (uint32_t idx = 0; (create_object_file_callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != NULL; ++idx)
+ for (uint32_t idx = 0; (create_object_file_callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != nullptr; ++idx)
{
object_file_sp.reset (create_object_file_callback(module_sp, data_sp, data_offset, file, file_offset, file_size));
if (object_file_sp.get())
@@ -131,7 +133,7 @@ ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp,
// Check if this is a object container by iterating through
// all object container plugin instances and then trying to get
// an object file from the container.
- for (uint32_t idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != NULL; ++idx)
+ for (uint32_t idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != nullptr; ++idx)
{
std::unique_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module_sp, data_sp, data_offset, file, file_offset, file_size));
@@ -157,26 +159,26 @@ ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp,
DataBufferSP &data_sp)
{
ObjectFileSP object_file_sp;
-
+
if (module_sp)
{
Timer scoped_timer (__PRETTY_FUNCTION__,
"ObjectFile::FindPlugin (module = %s, process = %p, header_addr = 0x%" PRIx64 ")",
module_sp->GetFileSpec().GetPath().c_str(),
- process_sp.get(), header_addr);
+ static_cast<void*>(process_sp.get()), header_addr);
uint32_t idx;
-
+
// Check if this is a normal object file by iterating through
// all object file plugin instances.
ObjectFileCreateMemoryInstance create_callback;
- for (idx = 0; (create_callback = PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(idx)) != NULL; ++idx)
+ for (idx = 0; (create_callback = PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(idx)) != nullptr; ++idx)
{
object_file_sp.reset (create_callback(module_sp, data_sp, process_sp, header_addr));
if (object_file_sp.get())
return object_file_sp;
}
-
}
+
// We didn't find it, so clear our shared pointer in case it
// contains anything and return an empty shared pointer
object_file_sp.reset();
@@ -220,14 +222,14 @@ ObjectFile::GetModuleSpecifications (const lldb_private::FileSpec& file,
ObjectFileGetModuleSpecifications callback;
uint32_t i;
// Try the ObjectFile plug-ins
- for (i = 0; (callback = PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex(i)) != NULL; ++i)
+ for (i = 0; (callback = PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex(i)) != nullptr; ++i)
{
if (callback (file, data_sp, data_offset, file_offset, file_size, specs) > 0)
return specs.GetSize() - initial_count;
}
// Try the ObjectContainer plug-ins
- for (i = 0; (callback = PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex(i)) != NULL; ++i)
+ for (i = 0; (callback = PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex(i)) != nullptr; ++i)
{
if (callback (file, data_sp, data_offset, file_offset, file_size, specs) > 0)
return specs.GetSize() - initial_count;
@@ -239,7 +241,7 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
const FileSpec *file_spec_ptr,
lldb::offset_t file_offset,
lldb::offset_t length,
- lldb::DataBufferSP& data_sp,
+ const lldb::DataBufferSP& data_sp,
lldb::offset_t data_offset
) :
ModuleChild (module_sp),
@@ -261,27 +263,12 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
m_data.SetData (data_sp, data_offset, length);
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- {
- if (m_file)
- {
- log->Printf ("%p ObjectFile::ObjectFile() module = %p (%s), file = %s, file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64,
- this,
- module_sp.get(),
- module_sp->GetSpecificationDescription().c_str(),
- m_file.GetPath().c_str(),
- m_file_offset,
- m_length);
- }
- else
- {
- log->Printf ("%p ObjectFile::ObjectFile() module = %p (%s), file = <NULL>, file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64,
- this,
- module_sp.get(),
- module_sp->GetSpecificationDescription().c_str(),
- m_file_offset,
- m_length);
- }
- }
+ log->Printf ("%p ObjectFile::ObjectFile() module = %p (%s), file = %s, file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64,
+ static_cast<void*>(this),
+ static_cast<void*>(module_sp.get()),
+ module_sp->GetSpecificationDescription().c_str(),
+ m_file ? m_file.GetPath().c_str() : "<NULL>",
+ m_file_offset, m_length);
}
@@ -306,14 +293,11 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize());
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- {
log->Printf ("%p ObjectFile::ObjectFile() module = %p (%s), process = %p, header_addr = 0x%" PRIx64,
- this,
- module_sp.get(),
+ static_cast<void*>(this),
+ static_cast<void*>(module_sp.get()),
module_sp->GetSpecificationDescription().c_str(),
- process_sp.get(),
- m_memory_addr);
- }
+ static_cast<void*>(process_sp.get()), m_memory_addr);
}
@@ -321,7 +305,8 @@ ObjectFile::~ObjectFile()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p ObjectFile::~ObjectFile ()\n", this);
+ log->Printf ("%p ObjectFile::~ObjectFile ()\n",
+ static_cast<void*>(this));
}
bool
@@ -350,9 +335,12 @@ ObjectFile::GetAddressClass (addr_t file_addr)
const SectionType section_type = section_sp->GetType();
switch (section_type)
{
- case eSectionTypeInvalid: return eAddressClassUnknown;
- case eSectionTypeCode: return eAddressClassCode;
- case eSectionTypeContainer: return eAddressClassUnknown;
+ case eSectionTypeInvalid:
+ return eAddressClassUnknown;
+ case eSectionTypeCode:
+ return eAddressClassCode;
+ case eSectionTypeContainer:
+ return eAddressClassUnknown;
case eSectionTypeData:
case eSectionTypeDataCString:
case eSectionTypeDataCStringPointers:
@@ -382,16 +370,18 @@ ObjectFile::GetAddressClass (addr_t file_addr)
case eSectionTypeDWARFAppleNamespaces:
case eSectionTypeDWARFAppleObjC:
return eAddressClassDebug;
- case eSectionTypeEHFrame: return eAddressClassRuntime;
+ case eSectionTypeEHFrame:
+ return eAddressClassRuntime;
case eSectionTypeELFSymbolTable:
case eSectionTypeELFDynamicSymbols:
case eSectionTypeELFRelocationEntries:
case eSectionTypeELFDynamicLinkInfo:
- case eSectionTypeOther: return eAddressClassUnknown;
+ case eSectionTypeOther:
+ return eAddressClassUnknown;
}
}
}
-
+
const SymbolType symbol_type = symbol->GetType();
switch (symbol_type)
{
@@ -449,7 +439,7 @@ ObjectFile::ReadMemory (const ProcessSP &process_sp, lldb::addr_t addr, size_t b
}
size_t
-ObjectFile::GetData (off_t offset, size_t length, DataExtractor &data) const
+ObjectFile::GetData (lldb::offset_t offset, size_t length, DataExtractor &data) const
{
// The entire file has already been mmap'ed into m_data, so just copy from there
// as the back mmap buffer will be shared with shared pointers.
@@ -457,7 +447,7 @@ ObjectFile::GetData (off_t offset, size_t length, DataExtractor &data) const
}
size_t
-ObjectFile::CopyData (off_t offset, size_t length, void *dst) const
+ObjectFile::CopyData (lldb::offset_t offset, size_t length, void *dst) const
{
// The entire file has already been mmap'ed into m_data, so just copy from there
// Note that the data remains in target byte order.
@@ -466,7 +456,7 @@ ObjectFile::CopyData (off_t offset, size_t length, void *dst) const
size_t
-ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void *dst, size_t dst_len) const
+ObjectFile::ReadSectionData (const Section *section, lldb::offset_t section_offset, void *dst, size_t dst_len) const
{
// If some other objectfile owns this data, pass this to them.
if (section->GetObjectFile() != this)
@@ -485,11 +475,11 @@ ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void
}
else
{
- const uint64_t section_file_size = section->GetFileSize();
+ const lldb::offset_t section_file_size = section->GetFileSize();
if (section_offset < section_file_size)
{
- const uint64_t section_bytes_left = section_file_size - section_offset;
- uint64_t section_dst_len = dst_len;
+ const size_t section_bytes_left = section_file_size - section_offset;
+ size_t section_dst_len = dst_len;
if (section_dst_len > section_bytes_left)
section_dst_len = section_bytes_left;
return CopyData (section->GetFileOffset() + section_offset, section_dst_len, dst);
@@ -601,11 +591,9 @@ ObjectFile::ClearSymtab ()
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- {
log->Printf ("%p ObjectFile::ClearSymtab () symtab = %p",
- this,
- m_symtab_ap.get());
- }
+ static_cast<void*>(this),
+ static_cast<void*>(m_symtab_ap.get()));
m_symtab_ap.reset();
}
}
@@ -613,11 +601,14 @@ ObjectFile::ClearSymtab ()
SectionList *
ObjectFile::GetSectionList()
{
- if (m_sections_ap.get() == NULL)
+ if (m_sections_ap.get() == nullptr)
{
ModuleSP module_sp(GetModule());
if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
CreateSections(*module_sp->GetUnifiedSectionList());
+ }
}
return m_sections_ap.get();
}
diff --git a/source/Symbol/Symbol.cpp b/source/Symbol/Symbol.cpp
index 6311a329739e..880519955277 100644
--- a/source/Symbol/Symbol.cpp
+++ b/source/Symbol/Symbol.cpp
@@ -174,7 +174,7 @@ Symbol::Clear()
bool
Symbol::ValueIsAddress() const
{
- return m_addr_range.GetBaseAddress().GetSection().get() != NULL;
+ return m_addr_range.GetBaseAddress().GetSection().get() != nullptr;
}
ConstString
@@ -312,7 +312,7 @@ Symbol::Dump(Stream *s, Target *target, uint32_t index) const
if (ValueIsAddress())
{
- if (!m_addr_range.GetBaseAddress().Dump(s, NULL, Address::DumpStyleFileAddress))
+ if (!m_addr_range.GetBaseAddress().Dump(s, nullptr, Address::DumpStyleFileAddress))
s->Printf("%*s", 18, "");
s->PutChar(' ');
@@ -536,49 +536,129 @@ Symbol::GetByteSize () const
return m_addr_range.GetByteSize();
}
+
Symbol *
-Symbol::ResolveReExportedSymbol (Target &target)
+Symbol::ResolveReExportedSymbolInModuleSpec (Target &target,
+ ConstString &reexport_name,
+ ModuleSpec &module_spec,
+ ModuleList &seen_modules) const
{
- ConstString reexport_name (GetReExportedSymbolName());
- if (reexport_name)
+ ModuleSP module_sp;
+ if (module_spec.GetFileSpec())
{
- ModuleSpec module_spec;
- ModuleSP module_sp;
- module_spec.GetFileSpec() = GetReExportedSymbolSharedLibrary();
- if (module_spec.GetFileSpec())
+ // Try searching for the module file spec first using the full path
+ module_sp = target.GetImages().FindFirstModule(module_spec);
+ if (!module_sp)
{
- // Try searching for the module file spec first using the full path
+ // Next try and find the module by basename in case environment
+ // variables or other runtime trickery causes shared libraries
+ // to be loaded from alternate paths
+ module_spec.GetFileSpec().GetDirectory().Clear();
module_sp = target.GetImages().FindFirstModule(module_spec);
- if (!module_sp)
- {
- // Next try and find the module by basename in case environment
- // variables or other runtime trickery causes shared libraries
- // to be loaded from alternate paths
- module_spec.GetFileSpec().GetDirectory().Clear();
- module_sp = target.GetImages().FindFirstModule(module_spec);
- }
}
+ }
+
+ if (module_sp)
+ {
+ // There should not be cycles in the reexport list, but we don't want to crash if there are so make sure
+ // we haven't seen this before:
+ if (!seen_modules.AppendIfNeeded(module_sp))
+ return nullptr;
- if (module_sp)
+ lldb_private::SymbolContextList sc_list;
+ module_sp->FindSymbolsWithNameAndType(reexport_name, eSymbolTypeAny, sc_list);
+ const size_t num_scs = sc_list.GetSize();
+ if (num_scs > 0)
{
- lldb_private::SymbolContextList sc_list;
- module_sp->FindSymbolsWithNameAndType(reexport_name, eSymbolTypeAny, sc_list);
- const size_t num_scs = sc_list.GetSize();
- if (num_scs > 0)
+ for (size_t i=0; i<num_scs; ++i)
{
- for (size_t i=0; i<num_scs; ++i)
+ lldb_private::SymbolContext sc;
+ if (sc_list.GetContextAtIndex(i, sc))
{
- lldb_private::SymbolContext sc;
- if (sc_list.GetContextAtIndex(i, sc))
- {
- if (sc.symbol->IsExternal())
- return sc.symbol;
- }
+ if (sc.symbol->IsExternal())
+ return sc.symbol;
}
}
}
+ // If we didn't find the symbol in this module, it may be because this module re-exports some
+ // whole other library. We have to search those as well:
+ seen_modules.Append(module_sp);
+
+ FileSpecList reexported_libraries = module_sp->GetObjectFile()->GetReExportedLibraries();
+ size_t num_reexported_libraries = reexported_libraries.GetSize();
+ for (size_t idx = 0; idx < num_reexported_libraries; idx++)
+ {
+ ModuleSpec reexported_module_spec;
+ reexported_module_spec.GetFileSpec() = reexported_libraries.GetFileSpecAtIndex(idx);
+ Symbol *result_symbol = ResolveReExportedSymbolInModuleSpec(target,
+ reexport_name,
+ reexported_module_spec,
+ seen_modules);
+ if (result_symbol)
+ return result_symbol;
+ }
+ }
+ return nullptr;
+}
+
+Symbol *
+Symbol::ResolveReExportedSymbol (Target &target) const
+{
+ ConstString reexport_name (GetReExportedSymbolName());
+ if (reexport_name)
+ {
+ ModuleSpec module_spec;
+ ModuleList seen_modules;
+ module_spec.GetFileSpec() = GetReExportedSymbolSharedLibrary();
+ if (module_spec.GetFileSpec())
+ {
+ return ResolveReExportedSymbolInModuleSpec(target, reexport_name, module_spec, seen_modules);
+ }
+ }
+ return nullptr;
+}
+
+lldb::addr_t
+Symbol::ResolveCallableAddress(Target &target) const
+{
+ if (GetType() == lldb::eSymbolTypeUndefined)
+ return LLDB_INVALID_ADDRESS;
+
+ Address func_so_addr;
+
+ bool is_indirect;
+ if (GetType() == eSymbolTypeReExported)
+ {
+ Symbol *reexported_symbol = ResolveReExportedSymbol(target);
+ if (reexported_symbol)
+ {
+ func_so_addr = reexported_symbol->GetAddress();
+ is_indirect = reexported_symbol->IsIndirect();
+ }
}
- return NULL;
+ else
+ {
+ func_so_addr = GetAddress();
+ is_indirect = IsIndirect();
+ }
+
+ if (func_so_addr.IsValid())
+ {
+ if (!target.GetProcessSP() && is_indirect)
+ {
+ // can't resolve indirect symbols without calling a function...
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ lldb::addr_t load_addr = func_so_addr.GetCallableLoadAddress (&target, is_indirect);
+
+ if (load_addr != LLDB_INVALID_ADDRESS)
+ {
+ return load_addr;
+ }
+ }
+
+ return LLDB_INVALID_ADDRESS;
}
@@ -592,7 +672,7 @@ Symbol::GetInstructions (const ExecutionContext &exe_ctx,
{
const bool prefer_file_cache = false;
return Disassembler::DisassembleRange (module_sp->GetArchitecture(),
- NULL,
+ nullptr,
flavor,
exe_ctx,
m_addr_range,
diff --git a/source/Symbol/SymbolContext.cpp b/source/Symbol/SymbolContext.cpp
index f1e581f71613..0e390dd08c5f 100644
--- a/source/Symbol/SymbolContext.cpp
+++ b/source/Symbol/SymbolContext.cpp
@@ -29,11 +29,11 @@ using namespace lldb_private;
SymbolContext::SymbolContext() :
target_sp (),
module_sp (),
- comp_unit (NULL),
- function (NULL),
- block (NULL),
+ comp_unit (nullptr),
+ function (nullptr),
+ block (nullptr),
line_entry (),
- symbol (NULL)
+ symbol (nullptr)
{
}
@@ -78,11 +78,11 @@ SymbolContext::SymbolContext(const SymbolContext& rhs) :
SymbolContext::SymbolContext (SymbolContextScope *sc_scope) :
target_sp (),
module_sp (),
- comp_unit (NULL),
- function (NULL),
- block (NULL),
+ comp_unit (nullptr),
+ function (nullptr),
+ block (nullptr),
line_entry (),
- symbol (NULL)
+ symbol (nullptr)
{
sc_scope->CalculateSymbolContext (this);
}
@@ -113,11 +113,11 @@ SymbolContext::Clear(bool clear_target)
if (clear_target)
target_sp.reset();
module_sp.reset();
- comp_unit = NULL;
- function = NULL;
- block = NULL;
+ comp_unit = nullptr;
+ function = nullptr;
+ block = nullptr;
line_entry.Clear();
- symbol = NULL;
+ symbol = nullptr;
}
bool
@@ -142,7 +142,7 @@ SymbolContext::DumpStopContext
dumped_something = true;
}
- if (function != NULL)
+ if (function != nullptr)
{
SymbolContext inline_parent_sc;
Address inline_parent_addr;
@@ -202,7 +202,7 @@ SymbolContext::DumpStopContext
}
}
}
- else if (symbol != NULL)
+ else if (symbol != nullptr)
{
if (symbol->GetMangled().GetName())
{
@@ -243,14 +243,14 @@ SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *t
s->EOL();
}
- if (comp_unit != NULL)
+ if (comp_unit != nullptr)
{
s->Indent("CompileUnit: ");
comp_unit->GetDescription (s, level);
s->EOL();
}
- if (function != NULL)
+ if (function != nullptr)
{
s->Indent(" Function: ");
function->GetDescription (s, level, target);
@@ -265,7 +265,7 @@ SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *t
}
}
- if (block != NULL)
+ if (block != nullptr)
{
std::vector<Block *> blocks;
blocks.push_back (block);
@@ -297,7 +297,7 @@ SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *t
s->EOL();
}
- if (symbol != NULL)
+ if (symbol != nullptr)
{
s->Indent(" Symbol: ");
symbol->GetDescription(s, level, target);
@@ -335,12 +335,12 @@ SymbolContext::Dump(Stream *s, Target *target) const
s->EOL();
s->Indent();
*s << "CompileUnit = " << (void *)comp_unit;
- if (comp_unit != NULL)
+ if (comp_unit != nullptr)
*s << " {0x" << comp_unit->GetID() << "} " << *(static_cast<FileSpec*> (comp_unit));
s->EOL();
s->Indent();
*s << "Function = " << (void *)function;
- if (function != NULL)
+ if (function != nullptr)
{
*s << " {0x" << function->GetID() << "} " << function->GetType()->GetName() << ", address-range = ";
function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
@@ -356,7 +356,7 @@ SymbolContext::Dump(Stream *s, Target *target) const
s->EOL();
s->Indent();
*s << "Block = " << (void *)block;
- if (block != NULL)
+ if (block != nullptr)
*s << " {0x" << block->GetID() << '}';
// Dump the block and pass it a negative depth to we print all the parent blocks
//if (block != NULL)
@@ -368,7 +368,7 @@ SymbolContext::Dump(Stream *s, Target *target) const
s->EOL();
s->Indent();
*s << "Symbol = " << (void *)symbol;
- if (symbol != NULL && symbol->GetMangled())
+ if (symbol != nullptr && symbol->GetMangled())
*s << ' ' << symbol->GetMangled().GetName().AsCString();
s->EOL();
s->IndentLess();
@@ -409,7 +409,7 @@ SymbolContext::GetAddressRange (uint32_t scope,
return true;
}
- if ((scope & eSymbolContextBlock) && (block != NULL))
+ if ((scope & eSymbolContextBlock) && (block != nullptr))
{
if (use_inline_block_range)
{
@@ -423,7 +423,7 @@ SymbolContext::GetAddressRange (uint32_t scope,
}
}
- if ((scope & eSymbolContextFunction) && (function != NULL))
+ if ((scope & eSymbolContextFunction) && (function != nullptr))
{
if (range_idx == 0)
{
@@ -432,7 +432,7 @@ SymbolContext::GetAddressRange (uint32_t scope,
}
}
- if ((scope & eSymbolContextSymbol) && (symbol != NULL))
+ if ((scope & eSymbolContextSymbol) && (symbol != nullptr))
{
if (range_idx == 0)
{
@@ -562,7 +562,7 @@ SymbolContext::GetFunctionBlock ()
// the function itself.
return &function->GetBlock(true);
}
- return NULL;
+ return nullptr;
}
bool
@@ -777,7 +777,7 @@ SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
{
if (sc.module_sp)
{
- if (m_module_sp.get() != NULL)
+ if (m_module_sp.get() != nullptr)
{
if (m_module_sp.get() != sc.module_sp.get())
return false;
@@ -795,15 +795,15 @@ SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
if (m_file_spec_ap.get())
{
// If we don't have a block or a comp_unit, then we aren't going to match a source file.
- if (sc.block == NULL && sc.comp_unit == NULL)
+ if (sc.block == nullptr && sc.comp_unit == nullptr)
return false;
// Check if the block is present, and if so is it inlined:
bool was_inlined = false;
- if (sc.block != NULL)
+ if (sc.block != nullptr)
{
const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
- if (inline_info != NULL)
+ if (inline_info != nullptr)
{
was_inlined = true;
if (!FileSpec::Equal (inline_info->GetDeclaration().GetFile(), *(m_file_spec_ap.get()), false))
@@ -812,7 +812,7 @@ SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
}
// Next check the comp unit, but only if the SymbolContext was not inlined.
- if (!was_inlined && sc.comp_unit != NULL)
+ if (!was_inlined && sc.comp_unit != nullptr)
{
if (!FileSpec::Equal (*(sc.comp_unit), *(m_file_spec_ap.get()), false))
return false;
@@ -832,10 +832,10 @@ SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
bool was_inlined = false;
ConstString func_name(m_function_spec.c_str());
- if (sc.block != NULL)
+ if (sc.block != nullptr)
{
const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
- if (inline_info != NULL)
+ if (inline_info != nullptr)
{
was_inlined = true;
const Mangled &name = inline_info->GetMangled();
@@ -846,12 +846,12 @@ SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
// If it wasn't inlined, check the name in the function or symbol:
if (!was_inlined)
{
- if (sc.function != NULL)
+ if (sc.function != nullptr)
{
if (!sc.function->GetMangled().NameMatches(func_name))
return false;
}
- else if (sc.symbol != NULL)
+ else if (sc.symbol != nullptr)
{
if (!sc.symbol->GetMangled().NameMatches(func_name))
return false;
@@ -873,7 +873,7 @@ SymbolContextSpecifier::AddressMatches(lldb::addr_t addr)
}
else
{
- Address match_address (addr, NULL);
+ Address match_address (addr, nullptr);
SymbolContext sc;
m_target_sp->GetImages().ResolveSymbolContextForAddress(match_address, eSymbolContextEverything, sc);
return SymbolContextMatches(sc);
@@ -903,22 +903,22 @@ SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level)
s->Printf ("Module: %s\n", m_module_spec.c_str());
}
- if (m_type == eFileSpecified && m_file_spec_ap.get() != NULL)
+ if (m_type == eFileSpecified && m_file_spec_ap.get() != nullptr)
{
m_file_spec_ap->GetPath (path_str, PATH_MAX);
s->Indent();
s->Printf ("File: %s", path_str);
if (m_type == eLineStartSpecified)
{
- s->Printf (" from line %zu", m_start_line);
+ s->Printf (" from line %" PRIu64 "", (uint64_t)m_start_line);
if (m_type == eLineEndSpecified)
- s->Printf ("to line %zu", m_end_line);
+ s->Printf ("to line %" PRIu64 "", (uint64_t)m_end_line);
else
s->Printf ("to end");
}
else if (m_type == eLineEndSpecified)
{
- s->Printf (" from start to line %zu", m_end_line);
+ s->Printf (" from start to line %" PRIu64 "", (uint64_t)m_end_line);
}
s->Printf (".\n");
}
@@ -926,16 +926,16 @@ SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level)
if (m_type == eLineStartSpecified)
{
s->Indent();
- s->Printf ("From line %zu", m_start_line);
+ s->Printf ("From line %" PRIu64 "", (uint64_t)m_start_line);
if (m_type == eLineEndSpecified)
- s->Printf ("to line %zu", m_end_line);
+ s->Printf ("to line %" PRIu64 "", (uint64_t)m_end_line);
else
s->Printf ("to end");
s->Printf (".\n");
}
else if (m_type == eLineEndSpecified)
{
- s->Printf ("From start to line %zu.\n", m_end_line);
+ s->Printf ("From start to line %" PRIu64 ".\n", (uint64_t)m_end_line);
}
if (m_type == eFunctionSpecified)
@@ -950,7 +950,7 @@ SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level)
s->Printf ("Class name: %s.\n", m_class_name.c_str());
}
- if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != NULL)
+ if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != nullptr)
{
s->Indent();
s->PutCString ("Address range: ");
@@ -1013,10 +1013,10 @@ SymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_in
return false;
}
if (merge_symbol_into_function
- && sc.symbol != NULL
- && sc.comp_unit == NULL
- && sc.function == NULL
- && sc.block == NULL
+ && sc.symbol != nullptr
+ && sc.comp_unit == nullptr
+ && sc.function == nullptr
+ && sc.block == nullptr
&& sc.line_entry.IsValid() == false)
{
if (sc.symbol->ValueIsAddress())
@@ -1034,7 +1034,7 @@ SymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_in
// Do we already have a function with this symbol?
if (pos->symbol == sc.symbol)
return false;
- if (pos->symbol == NULL)
+ if (pos->symbol == nullptr)
{
pos->symbol = sc.symbol;
return false;
@@ -1053,10 +1053,10 @@ SymbolContextList::MergeSymbolContextIntoFunctionContext (const SymbolContext& s
uint32_t start_idx,
uint32_t stop_idx)
{
- if (symbol_sc.symbol != NULL
- && symbol_sc.comp_unit == NULL
- && symbol_sc.function == NULL
- && symbol_sc.block == NULL
+ if (symbol_sc.symbol != nullptr
+ && symbol_sc.comp_unit == nullptr
+ && symbol_sc.function == nullptr
+ && symbol_sc.block == nullptr
&& symbol_sc.line_entry.IsValid() == false)
{
if (symbol_sc.symbol->ValueIsAddress())
@@ -1077,7 +1077,7 @@ SymbolContextList::MergeSymbolContextIntoFunctionContext (const SymbolContext& s
if (function_sc.symbol == symbol_sc.symbol)
return true; // Already have a symbol context with this symbol, return true
- if (function_sc.symbol == NULL)
+ if (function_sc.symbol == nullptr)
{
// We successfully merged this symbol into an existing symbol context
m_symbol_contexts[i].symbol = symbol_sc.symbol;
diff --git a/source/Symbol/SymbolFile.cpp b/source/Symbol/SymbolFile.cpp
index 412c4600c9f7..a5b138bb52af 100644
--- a/source/Symbol/SymbolFile.cpp
+++ b/source/Symbol/SymbolFile.cpp
@@ -22,7 +22,7 @@ SymbolFile*
SymbolFile::FindPlugin (ObjectFile* obj_file)
{
std::unique_ptr<SymbolFile> best_symfile_ap;
- if (obj_file != NULL)
+ if (obj_file != nullptr)
{
// We need to test the abilities of this section list. So create what it would
@@ -46,7 +46,7 @@ SymbolFile::FindPlugin (ObjectFile* obj_file)
uint32_t best_symfile_abilities = 0;
SymbolFileCreateInstance create_callback;
- for (uint32_t idx = 0; (create_callback = PluginManager::GetSymbolFileCreateCallbackAtIndex(idx)) != NULL; ++idx)
+ for (uint32_t idx = 0; (create_callback = PluginManager::GetSymbolFileCreateCallbackAtIndex(idx)) != nullptr; ++idx)
{
std::unique_ptr<SymbolFile> curr_symfile_ap(create_callback(obj_file));
@@ -79,7 +79,7 @@ SymbolFile::GetTypeList ()
{
if (m_obj_file)
return m_obj_file->GetModule()->GetTypeList();
- return NULL;
+ return nullptr;
}
lldb_private::ClangASTContext &
diff --git a/source/Symbol/SymbolVendor.cpp b/source/Symbol/SymbolVendor.cpp
index b51ac5a550fb..a3f4104016e5 100644
--- a/source/Symbol/SymbolVendor.cpp
+++ b/source/Symbol/SymbolVendor.cpp
@@ -37,7 +37,7 @@ SymbolVendor::FindPlugin (const lldb::ModuleSP &module_sp, lldb_private::Stream
std::unique_ptr<SymbolVendor> instance_ap;
SymbolVendorCreateInstance create_callback;
- for (size_t idx = 0; (create_callback = PluginManager::GetSymbolVendorCreateCallbackAtIndex(idx)) != NULL; ++idx)
+ for (size_t idx = 0; (create_callback = PluginManager::GetSymbolVendorCreateCallbackAtIndex(idx)) != nullptr; ++idx)
{
instance_ap.reset(create_callback(module_sp, feedback_strm));
@@ -109,7 +109,7 @@ SymbolVendor::SetCompileUnitAtIndex (size_t idx, const CompUnitSP &cu_sp)
// unit once, so if this assertion fails, we need to make sure that
// we don't have a race condition, or have a second parse of the same
// compile unit.
- assert(m_compile_units[idx].get() == NULL);
+ assert(m_compile_units[idx].get() == nullptr);
m_compile_units[idx] = cu_sp;
return true;
}
@@ -247,7 +247,7 @@ SymbolVendor::ResolveTypeUID(lldb::user_id_t type_uid)
if (m_sym_file_ap.get())
return m_sym_file_ap->ResolveTypeUID(type_uid);
}
- return NULL;
+ return nullptr;
}
@@ -382,7 +382,7 @@ SymbolVendor::Dump(Stream *s)
{
bool show_context = false;
- s->Printf("%p: ", this);
+ s->Printf("%p: ", static_cast<void*>(this));
s->Indent();
s->PutCString("SymbolVendor");
if (m_sym_file_ap.get())
@@ -427,7 +427,7 @@ SymbolVendor::GetCompileUnitAtIndex(size_t idx)
if (idx < num_compile_units)
{
cu_sp = m_compile_units[idx];
- if (cu_sp.get() == NULL)
+ if (cu_sp.get() == nullptr)
{
m_compile_units[idx] = m_sym_file_ap->ParseCompileUnitAtIndex(idx);
cu_sp = m_compile_units[idx];
@@ -450,7 +450,7 @@ SymbolVendor::GetSymtab ()
return objfile->GetSymtab ();
}
}
- return NULL;
+ return nullptr;
}
void
@@ -468,6 +468,27 @@ SymbolVendor::ClearSymtab()
}
}
+void
+SymbolVendor::SectionFileAddressesChanged ()
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ ObjectFile *module_objfile = module_sp->GetObjectFile ();
+ if (m_sym_file_ap.get())
+ {
+ ObjectFile *symfile_objfile = m_sym_file_ap->GetObjectFile ();
+ if (symfile_objfile != module_objfile)
+ symfile_objfile->SectionFileAddressesChanged ();
+ }
+ Symtab *symtab = GetSymtab ();
+ if (symtab)
+ {
+ symtab->SectionFileAddressesChanged ();
+ }
+ }
+}
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
diff --git a/source/Symbol/Symtab.cpp b/source/Symbol/Symtab.cpp
index 430fc1789202..907072c0d906 100644
--- a/source/Symbol/Symtab.cpp
+++ b/source/Symbol/Symtab.cpp
@@ -78,6 +78,13 @@ Symtab::GetNumSymbols() const
}
void
+Symtab::SectionFileAddressesChanged ()
+{
+ m_name_to_index.Clear();
+ m_file_addr_to_index_computed = false;
+}
+
+void
Symtab::Dump (Stream *s, Target *target, SortOrder sort_order)
{
Mutex::Locker locker (m_mutex);
@@ -85,19 +92,19 @@ Symtab::Dump (Stream *s, Target *target, SortOrder sort_order)
// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
s->Indent();
const FileSpec &file_spec = m_objfile->GetFileSpec();
- const char * object_name = NULL;
+ const char * object_name = nullptr;
if (m_objfile->GetModule())
object_name = m_objfile->GetModule()->GetObjectName().GetCString();
if (file_spec)
- s->Printf("Symtab, file = %s%s%s%s, num_symbols = %zu",
+ s->Printf("Symtab, file = %s%s%s%s, num_symbols = %" PRIu64,
file_spec.GetPath().c_str(),
object_name ? "(" : "",
object_name ? object_name : "",
object_name ? ")" : "",
- m_symbols.size());
+ (uint64_t)m_symbols.size());
else
- s->Printf("Symtab, num_symbols = %zu", m_symbols.size());
+ s->Printf("Symtab, num_symbols = %" PRIu64 "", (uint64_t)m_symbols.size());
if (!m_symbols.empty())
{
@@ -166,7 +173,7 @@ Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const
const size_t num_symbols = GetNumSymbols();
//s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
s->Indent();
- s->Printf("Symtab %zu symbol indexes (%zu symbols total):\n", indexes.size(), m_symbols.size());
+ s->Printf("Symtab %" PRIu64 " symbol indexes (%" PRIu64 " symbols total):\n", (uint64_t)indexes.size(), (uint64_t)m_symbols.size());
s->IndentMore();
if (!indexes.empty())
@@ -232,7 +239,7 @@ Symtab::SymbolAtIndex(size_t idx)
// when calling this function to avoid performance issues.
if (idx < m_symbols.size())
return &m_symbols[idx];
- return NULL;
+ return nullptr;
}
@@ -243,7 +250,7 @@ Symtab::SymbolAtIndex(size_t idx) const
// when calling this function to avoid performance issues.
if (idx < m_symbols.size())
return &m_symbols[idx];
- return NULL;
+ return nullptr;
}
//----------------------------------------------------------------------
@@ -286,7 +293,7 @@ Symtab::InitNameIndexes()
// The "const char *" in "class_contexts" must come from a ConstString::GetCString()
std::set<const char *> class_contexts;
UniqueCStringMap<uint32_t> mangled_name_to_index;
- std::vector<const char *> symbol_contexts(num_symbols, NULL);
+ std::vector<const char *> symbol_contexts(num_symbols, nullptr);
for (entry.value = 0; entry.value<num_symbols; ++entry.value)
{
@@ -776,7 +783,7 @@ Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Vis
}
}
}
- return NULL;
+ return nullptr;
}
size_t
@@ -854,7 +861,7 @@ Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symb
}
}
}
- return NULL;
+ return nullptr;
}
typedef struct
@@ -867,36 +874,10 @@ typedef struct
} SymbolSearchInfo;
static int
-SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
-{
- const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
- if (curr_symbol == NULL)
- return -1;
-
- const addr_t info_file_addr = info->file_addr;
-
- // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address
- // range if the symbol has a section!
- if (curr_symbol->ValueIsAddress())
- {
- const addr_t curr_file_addr = curr_symbol->GetAddress().GetFileAddress();
- if (info_file_addr < curr_file_addr)
- return -1;
- if (info_file_addr > curr_file_addr)
- return +1;
- info->match_symbol = const_cast<Symbol *>(curr_symbol);
- info->match_index_ptr = index_ptr;
- return 0;
- }
-
- return -1;
-}
-
-static int
SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
{
const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
- if (symbol == NULL)
+ if (symbol == nullptr)
return -1;
const addr_t info_file_addr = info->file_addr;
@@ -921,19 +902,6 @@ SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
return -1;
}
-static SymbolSearchInfo
-FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
-{
- SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 };
- ::bsearch (&info,
- indexes,
- num_indexes,
- sizeof(uint32_t),
- (ComparisonFunction)SymbolWithClosestFileAddress);
- return info;
-}
-
-
void
Symtab::InitAddressIndexes()
{
@@ -1034,7 +1002,7 @@ Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* index
Mutex::Locker locker (m_mutex);
- SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
+ SymbolSearchInfo info = { this, file_addr, nullptr, nullptr, 0 };
::bsearch (&info,
indexes,
@@ -1064,7 +1032,7 @@ Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* index
if (info.match_offset < symbol_byte_size)
return info.match_symbol;
}
- return NULL;
+ return nullptr;
}
Symbol *
@@ -1078,7 +1046,7 @@ Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
const FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.FindEntryThatContains(file_addr);
if (entry)
return SymbolAtIndex(entry->data);
- return NULL;
+ return nullptr;
}
void
@@ -1157,7 +1125,7 @@ Symtab::FindFunctionSymbols (const ConstString &name,
{
const UniqueCStringMap<uint32_t>::Entry *match;
for (match = m_basename_to_index.FindFirstValueForName(name_cstr);
- match != NULL;
+ match != nullptr;
match = m_basename_to_index.FindNextValueForName(match))
{
symbol_indexes.push_back(match->value);
@@ -1174,7 +1142,7 @@ Symtab::FindFunctionSymbols (const ConstString &name,
{
const UniqueCStringMap<uint32_t>::Entry *match;
for (match = m_method_to_index.FindFirstValueForName(name_cstr);
- match != NULL;
+ match != nullptr;
match = m_method_to_index.FindNextValueForName(match))
{
symbol_indexes.push_back(match->value);
@@ -1191,7 +1159,7 @@ Symtab::FindFunctionSymbols (const ConstString &name,
{
const UniqueCStringMap<uint32_t>::Entry *match;
for (match = m_selector_to_index.FindFirstValueForName(name_cstr);
- match != NULL;
+ match != nullptr;
match = m_selector_to_index.FindNextValueForName(match))
{
symbol_indexes.push_back(match->value);
diff --git a/source/Symbol/Type.cpp b/source/Symbol/Type.cpp
index 073940e8a7f7..4eb538fb1352 100644
--- a/source/Symbol/Type.cpp
+++ b/source/Symbol/Type.cpp
@@ -30,6 +30,8 @@
#include "llvm/ADT/StringRef.h"
+#include "clang/AST/Decl.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -91,7 +93,7 @@ Type::Type
m_name (name),
m_symbol_file (symbol_file),
m_context (context),
- m_encoding_type (NULL),
+ m_encoding_type (nullptr),
m_encoding_uid (encoding_uid),
m_encoding_uid_type (encoding_uid_type),
m_byte_size (byte_size),
@@ -106,9 +108,9 @@ Type::Type () :
std::enable_shared_from_this<Type> (),
UserID (0),
m_name ("<INVALID TYPE>"),
- m_symbol_file (NULL),
- m_context (NULL),
- m_encoding_type (NULL),
+ m_symbol_file (nullptr),
+ m_context (nullptr),
+ m_encoding_type (nullptr),
m_encoding_uid (LLDB_INVALID_UID),
m_encoding_uid_type (eEncodingInvalid),
m_byte_size (0),
@@ -201,16 +203,16 @@ Type::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_name)
void
Type::Dump (Stream *s, bool show_context)
{
- s->Printf("%p: ", this);
+ s->Printf("%p: ", static_cast<void*>(this));
s->Indent();
- *s << "Type" << (const UserID&)*this << ' ';
+ *s << "Type" << static_cast<const UserID&>(*this) << ' ';
if (m_name)
*s << ", name = \"" << m_name << "\"";
if (m_byte_size != 0)
s->Printf(", size = %" PRIu64, m_byte_size);
- if (show_context && m_context != NULL)
+ if (show_context && m_context != nullptr)
{
s->PutCString(", context = ( ");
m_context->DumpSymbolContext(s);
@@ -306,7 +308,7 @@ Type::DumpValue
Type *
Type::GetEncodingType ()
{
- if (m_encoding_type == NULL && m_encoding_uid != LLDB_INVALID_UID)
+ if (m_encoding_type == nullptr && m_encoding_uid != LLDB_INVALID_UID)
m_encoding_type = m_symbol_file->ResolveTypeUID(m_encoding_uid);
return m_encoding_type;
}
@@ -406,7 +408,7 @@ Type::DumpValueInMemory
if (address != LLDB_INVALID_ADDRESS)
{
DataExtractor data;
- Target *target = NULL;
+ Target *target = nullptr;
if (exe_ctx)
target = exe_ctx->GetTargetPtr();
if (target)
@@ -439,14 +441,14 @@ Type::ReadFromMemory (ExecutionContext *exe_ctx, lldb::addr_t addr, AddressType
}
uint8_t* dst = (uint8_t*)data.PeekData(0, byte_size);
- if (dst != NULL)
+ if (dst != nullptr)
{
if (address_type == eAddressTypeHost)
{
// The address is an address in this process, so just copy it
if (addr == 0)
return false;
- memcpy (dst, (uint8_t*)NULL + addr, byte_size);
+ memcpy (dst, (uint8_t*)nullptr + addr, byte_size);
return true;
}
else
@@ -488,7 +490,7 @@ Type::GetDeclaration () const
bool
Type::ResolveClangType (ResolveState clang_type_resolve_state)
{
- Type *encoding_type = NULL;
+ Type *encoding_type = nullptr;
if (!m_clang_type.IsValid())
{
encoding_type = GetEncodingType();
@@ -603,7 +605,7 @@ Type::ResolveClangType (ResolveState clang_type_resolve_state)
// resolved appropriately.
if (m_encoding_uid != LLDB_INVALID_UID)
{
- if (encoding_type == NULL)
+ if (encoding_type == nullptr)
encoding_type = GetEncodingType();
if (encoding_type)
{
@@ -777,7 +779,7 @@ Type::GetTypeScopeAndBasename (const char* &name_cstr,
if (namespace_separator)
{
const char* template_arg_char = ::strchr (basename_cstr, '<');
- while (namespace_separator != NULL)
+ while (namespace_separator != nullptr)
{
if (template_arg_char && namespace_separator > template_arg_char) // but namespace'd template arguments are still good to go
break;
@@ -796,6 +798,13 @@ Type::GetTypeScopeAndBasename (const char* &name_cstr,
}
+ModuleSP
+Type::GetModule()
+{
+ if (m_symbol_file)
+ return m_symbol_file->GetObjectFile()->GetModule();
+ return ModuleSP();
+}
TypeAndOrName::TypeAndOrName () : m_type_pair(), m_type_name()
@@ -927,76 +936,95 @@ TypeAndOrName::HasClangASTType () const
TypeImpl::TypeImpl() :
-m_static_type(),
-m_dynamic_type()
+ m_module_wp(),
+ m_static_type(),
+ m_dynamic_type()
{
}
TypeImpl::TypeImpl(const TypeImpl& rhs) :
-m_static_type(rhs.m_static_type),
-m_dynamic_type(rhs.m_dynamic_type)
+ m_module_wp (rhs.m_module_wp),
+ m_static_type(rhs.m_static_type),
+ m_dynamic_type(rhs.m_dynamic_type)
{
}
-TypeImpl::TypeImpl (lldb::TypeSP type_sp) :
-m_static_type(type_sp),
-m_dynamic_type()
+TypeImpl::TypeImpl (const lldb::TypeSP &type_sp) :
+ m_module_wp (),
+ m_static_type(),
+ m_dynamic_type()
{
+ SetType (type_sp);
}
-TypeImpl::TypeImpl (ClangASTType clang_type) :
-m_static_type(clang_type),
-m_dynamic_type()
+TypeImpl::TypeImpl (const ClangASTType &clang_type) :
+ m_module_wp (),
+ m_static_type(),
+ m_dynamic_type()
{
+ SetType (clang_type);
}
-TypeImpl::TypeImpl (lldb::TypeSP type_sp, ClangASTType dynamic) :
-m_static_type (type_sp),
-m_dynamic_type(dynamic)
+TypeImpl::TypeImpl (const lldb::TypeSP &type_sp, const ClangASTType &dynamic) :
+ m_module_wp (),
+ m_static_type (type_sp),
+ m_dynamic_type(dynamic)
{
+ SetType (type_sp, dynamic);
}
-TypeImpl::TypeImpl (ClangASTType clang_type, ClangASTType dynamic) :
-m_static_type (clang_type),
-m_dynamic_type(dynamic)
+TypeImpl::TypeImpl (const ClangASTType &static_type, const ClangASTType &dynamic_type) :
+ m_module_wp (),
+ m_static_type (),
+ m_dynamic_type()
{
+ SetType (static_type, dynamic_type);
}
-TypeImpl::TypeImpl (TypePair pair, ClangASTType dynamic) :
-m_static_type (pair),
-m_dynamic_type(dynamic)
+TypeImpl::TypeImpl (const TypePair &pair, const ClangASTType &dynamic) :
+ m_module_wp (),
+ m_static_type (),
+ m_dynamic_type()
{
+ SetType (pair, dynamic);
}
void
-TypeImpl::SetType (lldb::TypeSP type_sp)
+TypeImpl::SetType (const lldb::TypeSP &type_sp)
{
m_static_type.SetType(type_sp);
+ if (type_sp)
+ m_module_wp = type_sp->GetModule();
+ else
+ m_module_wp = lldb::ModuleWP();
}
void
-TypeImpl::SetType (ClangASTType clang_type)
+TypeImpl::SetType (const ClangASTType &clang_type)
{
+ m_module_wp = lldb::ModuleWP();
m_static_type.SetType (clang_type);
}
void
-TypeImpl::SetType (lldb::TypeSP type_sp, ClangASTType dynamic)
+TypeImpl::SetType (const lldb::TypeSP &type_sp, const ClangASTType &dynamic)
{
- m_static_type.SetType (type_sp);
+ SetType (type_sp);
m_dynamic_type = dynamic;
}
void
-TypeImpl::SetType (ClangASTType clang_type, ClangASTType dynamic)
+TypeImpl::SetType (const ClangASTType &clang_type, const ClangASTType &dynamic)
{
+ m_module_wp = lldb::ModuleWP();
m_static_type.SetType (clang_type);
m_dynamic_type = dynamic;
}
void
-TypeImpl::SetType (TypePair pair, ClangASTType dynamic)
+TypeImpl::SetType (const TypePair &pair, const ClangASTType &dynamic)
{
+ m_module_wp = pair.GetModule();
m_static_type = pair;
m_dynamic_type = dynamic;
}
@@ -1006,6 +1034,7 @@ TypeImpl::operator = (const TypeImpl& rhs)
{
if (rhs != *this)
{
+ m_module_wp = rhs.m_module_wp;
m_static_type = rhs.m_static_type;
m_dynamic_type = rhs.m_dynamic_type;
}
@@ -1013,24 +1042,55 @@ TypeImpl::operator = (const TypeImpl& rhs)
}
bool
+TypeImpl::CheckModule (lldb::ModuleSP &module_sp) const
+{
+ // Check if we have a module for this type. If we do and the shared pointer is
+ // can be successfully initialized with m_module_wp, return true. Else return false
+ // if we didn't have a module, or if we had a module and it has been deleted. Any
+ // functions doing anything with a TypeSP in this TypeImpl class should call this
+ // function and only do anything with the ivars if this function returns true. If
+ // we have a module, the "module_sp" will be filled in with a strong reference to the
+ // module so that the module will at least stay around long enough for the type
+ // query to succeed.
+ module_sp = m_module_wp.lock();
+ if (!module_sp)
+ {
+ lldb::ModuleWP empty_module_wp;
+ // If either call to "std::weak_ptr::owner_before(...) value returns true, this
+ // indicates that m_module_wp once contained (possibly still does) a reference
+ // to a valid shared pointer. This helps us know if we had a valid reference to
+ // a section which is now invalid because the module it was in was deleted
+ if (empty_module_wp.owner_before(m_module_wp) || m_module_wp.owner_before(empty_module_wp))
+ {
+ // m_module_wp had a valid reference to a module, but all strong references
+ // have been released and the module has been deleted
+ return false;
+ }
+ }
+ // We either successfully locked the module, or didn't have one to begin with
+ return true;
+}
+
+bool
TypeImpl::operator == (const TypeImpl& rhs) const
{
- return m_static_type == rhs.m_static_type &&
- m_dynamic_type == rhs.m_dynamic_type;
+ return m_static_type == rhs.m_static_type && m_dynamic_type == rhs.m_dynamic_type;
}
bool
TypeImpl::operator != (const TypeImpl& rhs) const
{
- return m_static_type != rhs.m_static_type ||
- m_dynamic_type != rhs.m_dynamic_type;
+ return m_static_type != rhs.m_static_type || m_dynamic_type != rhs.m_dynamic_type;
}
bool
TypeImpl::IsValid() const
{
// just a name is not valid
- return m_static_type.IsValid() || m_dynamic_type.IsValid();
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
+ return m_static_type.IsValid() || m_dynamic_type.IsValid();
+ return false;
}
TypeImpl::operator bool () const
@@ -1041,6 +1101,7 @@ TypeImpl::operator bool () const
void
TypeImpl::Clear()
{
+ m_module_wp = lldb::ModuleWP();
m_static_type.Clear();
m_dynamic_type.Clear();
}
@@ -1048,113 +1109,201 @@ TypeImpl::Clear()
ConstString
TypeImpl::GetName () const
{
- if (m_dynamic_type)
- return m_dynamic_type.GetTypeName();
- return m_static_type.GetName ();
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
+ {
+ if (m_dynamic_type)
+ return m_dynamic_type.GetTypeName();
+ return m_static_type.GetName ();
+ }
+ return ConstString();
+}
+
+ConstString
+TypeImpl::GetDisplayTypeName () const
+{
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
+ {
+ if (m_dynamic_type)
+ return m_dynamic_type.GetDisplayTypeName();
+ return m_static_type.GetDisplayTypeName();
+ }
+ return ConstString();
}
TypeImpl
TypeImpl::GetPointerType () const
{
- if (m_dynamic_type.IsValid())
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
{
- return TypeImpl(m_static_type, m_dynamic_type.GetPointerType());
+ if (m_dynamic_type.IsValid())
+ {
+ return TypeImpl(m_static_type, m_dynamic_type.GetPointerType());
+ }
+ return TypeImpl(m_static_type.GetPointerType());
}
- return TypeImpl(m_static_type.GetPointerType());
+ return TypeImpl();
}
TypeImpl
TypeImpl::GetPointeeType () const
{
- if (m_dynamic_type.IsValid())
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
{
- return TypeImpl(m_static_type, m_dynamic_type.GetPointeeType());
+ if (m_dynamic_type.IsValid())
+ {
+ return TypeImpl(m_static_type, m_dynamic_type.GetPointeeType());
+ }
+ return TypeImpl(m_static_type.GetPointeeType());
}
- return TypeImpl(m_static_type.GetPointeeType());
+ return TypeImpl();
}
TypeImpl
TypeImpl::GetReferenceType () const
{
- if (m_dynamic_type.IsValid())
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
{
- return TypeImpl(m_static_type, m_dynamic_type.GetLValueReferenceType());
+ if (m_dynamic_type.IsValid())
+ {
+ return TypeImpl(m_static_type, m_dynamic_type.GetLValueReferenceType());
+ }
+ return TypeImpl(m_static_type.GetReferenceType());
}
- return TypeImpl(m_static_type.GetReferenceType());
+ return TypeImpl();
}
TypeImpl
TypeImpl::GetTypedefedType () const
{
- if (m_dynamic_type.IsValid())
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
{
- return TypeImpl(m_static_type, m_dynamic_type.GetTypedefedType());
+ if (m_dynamic_type.IsValid())
+ {
+ return TypeImpl(m_static_type, m_dynamic_type.GetTypedefedType());
+ }
+ return TypeImpl(m_static_type.GetTypedefedType());
}
- return TypeImpl(m_static_type.GetTypedefedType());
+ return TypeImpl();
}
TypeImpl
TypeImpl::GetDereferencedType () const
{
- if (m_dynamic_type.IsValid())
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
{
- return TypeImpl(m_static_type, m_dynamic_type.GetNonReferenceType());
+ if (m_dynamic_type.IsValid())
+ {
+ return TypeImpl(m_static_type, m_dynamic_type.GetNonReferenceType());
+ }
+ return TypeImpl(m_static_type.GetDereferencedType());
}
- return TypeImpl(m_static_type.GetDereferencedType());
+ return TypeImpl();
}
TypeImpl
TypeImpl::GetUnqualifiedType() const
{
- if (m_dynamic_type.IsValid())
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
{
- return TypeImpl(m_static_type, m_dynamic_type.GetFullyUnqualifiedType());
+ if (m_dynamic_type.IsValid())
+ {
+ return TypeImpl(m_static_type, m_dynamic_type.GetFullyUnqualifiedType());
+ }
+ return TypeImpl(m_static_type.GetUnqualifiedType());
}
- return TypeImpl(m_static_type.GetUnqualifiedType());
+ return TypeImpl();
}
TypeImpl
TypeImpl::GetCanonicalType() const
{
- if (m_dynamic_type.IsValid())
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
{
- return TypeImpl(m_static_type, m_dynamic_type.GetCanonicalType());
+ if (m_dynamic_type.IsValid())
+ {
+ return TypeImpl(m_static_type, m_dynamic_type.GetCanonicalType());
+ }
+ return TypeImpl(m_static_type.GetCanonicalType());
}
- return TypeImpl(m_static_type.GetCanonicalType());
+ return TypeImpl();
}
ClangASTType
TypeImpl::GetClangASTType (bool prefer_dynamic)
{
- if (prefer_dynamic)
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
{
- if (m_dynamic_type.IsValid())
- return m_dynamic_type;
+ if (prefer_dynamic)
+ {
+ if (m_dynamic_type.IsValid())
+ return m_dynamic_type;
+ }
+ return m_static_type.GetClangASTType();
}
- return m_static_type.GetClangASTType();
+ return ClangASTType();
}
clang::ASTContext *
TypeImpl::GetClangASTContext (bool prefer_dynamic)
{
- if (prefer_dynamic)
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
{
- if (m_dynamic_type.IsValid())
- return m_dynamic_type.GetASTContext();
+ if (prefer_dynamic)
+ {
+ if (m_dynamic_type.IsValid())
+ return m_dynamic_type.GetASTContext();
+ }
+ return m_static_type.GetClangASTContext();
}
- return m_static_type.GetClangASTContext();
+ return NULL;
}
bool
TypeImpl::GetDescription (lldb_private::Stream &strm,
- lldb::DescriptionLevel description_level)
+ lldb::DescriptionLevel description_level)
{
- if (m_dynamic_type.IsValid())
+ ModuleSP module_sp;
+ if (CheckModule (module_sp))
{
- strm.Printf("Dynamic:\n");
- m_dynamic_type.DumpTypeDescription(&strm);
- strm.Printf("\nStatic:\n");
+ if (m_dynamic_type.IsValid())
+ {
+ strm.Printf("Dynamic:\n");
+ m_dynamic_type.DumpTypeDescription(&strm);
+ strm.Printf("\nStatic:\n");
+ }
+ m_static_type.GetClangASTType().DumpTypeDescription(&strm);
+ }
+ else
+ {
+ strm.PutCString("Invalid TypeImpl module for type has been deleted\n");
}
- m_static_type.GetClangASTType().DumpTypeDescription(&strm);
return true;
}
+
+TypeEnumMemberImpl::TypeEnumMemberImpl (const clang::EnumConstantDecl* enum_member_decl,
+ const lldb_private::ClangASTType& integer_type) :
+ m_integer_type_sp(),
+ m_name(),
+ m_value(),
+ m_valid(false)
+
+{
+ if (enum_member_decl)
+ {
+ m_integer_type_sp.reset(new TypeImpl(integer_type));
+ m_name = ConstString(enum_member_decl->getNameAsString().c_str());
+ m_value = enum_member_decl->getInitVal();
+ m_valid = true;
+ }
+}
diff --git a/source/Symbol/TypeList.cpp b/source/Symbol/TypeList.cpp
index a033edd22e1f..8d97b2ba25cc 100644
--- a/source/Symbol/TypeList.cpp
+++ b/source/Symbol/TypeList.cpp
@@ -179,49 +179,6 @@ TypeList::Dump(Stream *s, bool show_context)
}
}
-// depending on implementation details, type lookup might fail because of
-// embedded spurious namespace:: prefixes. this call strips them, paying
-// attention to the fact that a type might have namespace'd type names as
-// arguments to templates, and those must not be stripped off
-static bool
-GetTypeScopeAndBasename(const char* name_cstr, std::string &scope, std::string &basename, bool *exact_ptr)
-{
- // Protect against null c string.
-
- if (name_cstr && name_cstr[0])
- {
- const char *basename_cstr = name_cstr;
- const char* namespace_separator = ::strstr (basename_cstr, "::");
- if (namespace_separator)
- {
- const char* template_arg_char = ::strchr (basename_cstr, '<');
- while (namespace_separator != NULL)
- {
- if (template_arg_char && namespace_separator > template_arg_char) // but namespace'd template arguments are still good to go
- break;
- basename_cstr = namespace_separator + 2;
- namespace_separator = strstr(basename_cstr, "::");
- }
- if (basename_cstr > name_cstr)
- {
- scope.assign (name_cstr, basename_cstr - name_cstr);
- if (scope.size() >= 2 && scope[0] == ':' && scope[1] == ':')
- {
- // The typename passed in started with "::" so make sure we only do exact matches
- if (exact_ptr)
- *exact_ptr = true;
- // Strip the leading "::" as this won't ever show in qualified typenames we get
- // from clang.
- scope.erase(0,2);
- }
- basename.assign (basename_cstr);
- return true;
- }
- }
- }
- return false;
-}
-
void
TypeList::RemoveMismatchedTypes (const char *qualified_typename,
bool exact_match)
diff --git a/source/Symbol/UnwindPlan.cpp b/source/Symbol/UnwindPlan.cpp
index 7b361e7d2eb9..ff0468e314d8 100644
--- a/source/Symbol/UnwindPlan.cpp
+++ b/source/Symbol/UnwindPlan.cpp
@@ -126,7 +126,7 @@ UnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_pla
case inOtherRegister:
{
- const RegisterInfo *other_reg_info = NULL;
+ const RegisterInfo *other_reg_info = nullptr;
if (unwind_plan)
other_reg_info = unwind_plan->GetRegisterInfo (thread, m_location.reg_num);
if (other_reg_info)
@@ -313,6 +313,19 @@ UnwindPlan::AppendRow (const UnwindPlan::RowSP &row_sp)
m_row_list.back() = row_sp;
}
+void
+UnwindPlan::InsertRow (const UnwindPlan::RowSP &row_sp)
+{
+ collection::iterator it = m_row_list.begin();
+ while (it != m_row_list.end()) {
+ RowSP row = *it;
+ if (row->GetOffset() > row_sp->GetOffset())
+ break;
+ it++;
+ }
+ m_row_list.insert(it, row_sp);
+}
+
UnwindPlan::RowSP
UnwindPlan::GetRowForFunctionOffset (int offset) const
{
@@ -326,7 +339,7 @@ UnwindPlan::GetRowForFunctionOffset (int offset) const
collection::const_iterator pos, end = m_row_list.end();
for (pos = m_row_list.begin(); pos != end; ++pos)
{
- if ((*pos)->GetOffset() <= offset)
+ if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset))
row = *pos;
else
break;
@@ -381,7 +394,7 @@ UnwindPlan::PlanValidAtAddress (Address addr)
if (log)
{
StreamString s;
- if (addr.Dump (&s, NULL, Address::DumpStyleSectionNameOffset))
+ if (addr.Dump (&s, nullptr, Address::DumpStyleSectionNameOffset))
{
log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s' at address %s",
m_source_name.GetCString(), s.GetData());
@@ -397,13 +410,13 @@ UnwindPlan::PlanValidAtAddress (Address addr)
// If the 0th Row of unwind instructions is missing, or if it doesn't provide
// a register to use to find the Canonical Frame Address, this is not a valid UnwindPlan.
- if (GetRowAtIndex(0).get() == NULL || GetRowAtIndex(0)->GetCFARegister() == LLDB_INVALID_REGNUM)
+ if (GetRowAtIndex(0).get() == nullptr || GetRowAtIndex(0)->GetCFARegister() == LLDB_INVALID_REGNUM)
{
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
if (log)
{
StreamString s;
- if (addr.Dump (&s, NULL, Address::DumpStyleSectionNameOffset))
+ if (addr.Dump (&s, nullptr, Address::DumpStyleSectionNameOffset))
{
log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s' at address %s",
m_source_name.GetCString(), s.GetData());
@@ -480,6 +493,6 @@ UnwindPlan::GetRegisterInfo (Thread* thread, uint32_t unwind_reg) const
return reg_ctx->GetRegisterInfoAtIndex (reg);
}
}
- return NULL;
+ return nullptr;
}
diff --git a/source/Symbol/UnwindTable.cpp b/source/Symbol/UnwindTable.cpp
index 33eb4d6c092b..df9f5b932565 100644
--- a/source/Symbol/UnwindTable.cpp
+++ b/source/Symbol/UnwindTable.cpp
@@ -17,7 +17,6 @@
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
-#include "lldb/Target/UnwindAssembly.h"
// There is one UnwindTable object per ObjectFile.
// It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile.
@@ -30,8 +29,8 @@ UnwindTable::UnwindTable (ObjectFile& objfile) :
m_object_file (objfile),
m_unwinds (),
m_initialized (false),
- m_assembly_profiler (NULL),
- m_eh_frame (NULL)
+ m_mutex (),
+ m_eh_frame (nullptr)
{
}
@@ -44,6 +43,11 @@ UnwindTable::Initialize ()
if (m_initialized)
return;
+ Mutex::Locker locker(m_mutex);
+
+ if (m_initialized) // check again once we've acquired the lock
+ return;
+
SectionList* sl = m_object_file.GetSectionList ();
if (sl)
{
@@ -54,12 +58,7 @@ UnwindTable::Initialize ()
}
}
- ArchSpec arch;
- if (m_object_file.GetArchitecture (arch))
- {
- m_assembly_profiler = UnwindAssembly::FindPlugin (arch);
- m_initialized = true;
- }
+ m_initialized = true;
}
UnwindTable::~UnwindTable ()
@@ -75,6 +74,8 @@ UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolConte
Initialize();
+ Mutex::Locker locker(m_mutex);
+
// There is an UnwindTable per object file, so we can safely use file handles
addr_t file_addr = addr.GetFileAddress();
iterator end = m_unwinds.end ();
@@ -94,13 +95,13 @@ UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolConte
if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
{
// Does the eh_frame unwind info has a function bounds for this addr?
- if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range))
+ if (m_eh_frame == nullptr || !m_eh_frame->GetAddressRange (addr, range))
{
return no_unwind_found;
}
}
- FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range));
+ FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, range));
m_unwinds.insert (insert_pos, std::make_pair(range.GetBaseAddress().GetFileAddress(), func_unwinder_sp));
// StreamFile s(stdout, false);
// Dump (s);
@@ -121,13 +122,13 @@ UnwindTable::GetUncachedFuncUnwindersContainingAddress (const Address& addr, Sym
if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
{
// Does the eh_frame unwind info has a function bounds for this addr?
- if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range))
+ if (m_eh_frame == nullptr || !m_eh_frame->GetAddressRange (addr, range))
{
return no_unwind_found;
}
}
- FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range));
+ FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, range));
return func_unwinder_sp;
}
@@ -135,6 +136,7 @@ UnwindTable::GetUncachedFuncUnwindersContainingAddress (const Address& addr, Sym
void
UnwindTable::Dump (Stream &s)
{
+ Mutex::Locker locker(m_mutex);
s.Printf("UnwindTable for '%s':\n", m_object_file.GetFileSpec().GetPath().c_str());
const_iterator begin = m_unwinds.begin();
const_iterator end = m_unwinds.end();
@@ -151,3 +153,9 @@ UnwindTable::GetEHFrameInfo ()
Initialize();
return m_eh_frame;
}
+
+bool
+UnwindTable::GetArchitecture (lldb_private::ArchSpec &arch)
+{
+ return m_object_file.GetArchitecture (arch);
+}
diff --git a/source/Symbol/Variable.cpp b/source/Symbol/Variable.cpp
index 36fe3b1d79d4..e6a9b027fc13 100644
--- a/source/Symbol/Variable.cpp
+++ b/source/Symbol/Variable.cpp
@@ -87,13 +87,13 @@ Variable::GetType()
{
if (m_symfile_type_sp)
return m_symfile_type_sp->GetType();
- return NULL;
+ return nullptr;
}
void
Variable::Dump(Stream *s, bool show_context) const
{
- s->Printf("%p: ", this);
+ s->Printf("%p: ", static_cast<const void*>(this));
s->Indent();
*s << "Variable" << (const UserID&)*this;
@@ -123,7 +123,7 @@ Variable::Dump(Stream *s, bool show_context) const
}
}
- if (show_context && m_owner_scope != NULL)
+ if (show_context && m_owner_scope != nullptr)
{
s->PutCString(", context = ( ");
m_owner_scope->DumpSymbolContext(s);
@@ -144,7 +144,7 @@ Variable::Dump(Stream *s, bool show_context) const
if (variable_sc.function)
loclist_base_addr = variable_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
}
- ABI *abi = NULL;
+ ABI *abi = nullptr;
if (m_owner_scope)
{
ModuleSP module_sp (m_owner_scope->CalculateSymbolContextModule());
@@ -171,12 +171,12 @@ Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module)
{
SymbolContext sc;
m_owner_scope->CalculateSymbolContext(&sc);
- sc.block = NULL;
+ sc.block = nullptr;
sc.line_entry.Clear();
bool show_inlined_frames = false;
dumped_declaration_info = sc.DumpStopContext (s,
- NULL,
+ nullptr,
Address(),
show_fullpaths,
show_module,
@@ -277,7 +277,7 @@ Variable::IsInScope (StackFrame *frame)
{
case eValueTypeRegister:
case eValueTypeRegisterSet:
- return frame != NULL;
+ return frame != nullptr;
case eValueTypeConstResult:
case eValueTypeVariableGlobal:
@@ -297,7 +297,7 @@ Variable::IsInScope (StackFrame *frame)
CalculateSymbolContext (&variable_sc);
// Check for static or global variable defined at the compile unit
// level that wasn't defined in a block
- if (variable_sc.block == NULL)
+ if (variable_sc.block == nullptr)
return true;
if (variable_sc.block == deepest_frame_block)
@@ -419,7 +419,7 @@ Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path,
const char *variable_sub_expr_path = variable_expr_path + variable_name.size();
if (*variable_sub_expr_path)
{
- const char* first_unparsed = NULL;
+ const char* first_unparsed = nullptr;
ValueObject::ExpressionPathScanEndReason reason_to_stop;
ValueObject::ExpressionPathEndResultType final_value_type;
ValueObject::GetValueForExpressionPathOptions options;
@@ -485,7 +485,7 @@ Variable::DumpLocationForAddress (Stream *s, const Address &address)
CalculateSymbolContext(&sc);
if (sc.module_sp == address.GetModule())
{
- ABI *abi = NULL;
+ ABI *abi = nullptr;
if (m_owner_scope)
{
ModuleSP module_sp (m_owner_scope->CalculateSymbolContextModule());
@@ -553,7 +553,7 @@ PrivateAutoCompleteMembers (StackFrame *frame,
{
for (uint32_t i = 0; i < num_bases; ++i)
{
- ClangASTType base_class_type (clang_type.GetDirectBaseClassAtIndex (i, NULL));
+ ClangASTType base_class_type (clang_type.GetDirectBaseClassAtIndex (i, nullptr));
PrivateAutoCompleteMembers (frame,
partial_member_name,
@@ -571,7 +571,7 @@ PrivateAutoCompleteMembers (StackFrame *frame,
{
for (uint32_t i = 0; i < num_vbases; ++i)
{
- ClangASTType vbase_class_type (clang_type.GetVirtualBaseClassAtIndex(i,NULL));
+ ClangASTType vbase_class_type (clang_type.GetVirtualBaseClassAtIndex(i,nullptr));
PrivateAutoCompleteMembers (frame,
partial_member_name,
@@ -592,7 +592,7 @@ PrivateAutoCompleteMembers (StackFrame *frame,
{
std::string member_name;
- ClangASTType member_clang_type = clang_type.GetFieldAtIndex (i, member_name, NULL, NULL, NULL);
+ ClangASTType member_clang_type = clang_type.GetFieldAtIndex (i, member_name, nullptr, nullptr, nullptr);
if (partial_member_name.empty() ||
member_name.find(partial_member_name) == 0)
diff --git a/source/Target/ABI.cpp b/source/Target/ABI.cpp
index 06215221d961..e02f360680fb 100644
--- a/source/Target/ABI.cpp
+++ b/source/Target/ABI.cpp
@@ -51,7 +51,6 @@ ABI::~ABI()
{
}
-
bool
ABI::GetRegisterInfoByName (const ConstString &name, RegisterInfo &info)
{
@@ -172,4 +171,37 @@ ABI::GetReturnValueObject (Thread &thread,
return return_valobj_sp;
}
+ValueObjectSP
+ABI::GetReturnValueObject(Thread &thread, llvm::Type &ast_type, bool persistent) const
+{
+ ValueObjectSP return_valobj_sp;
+ return_valobj_sp = GetReturnValueObjectImpl( thread, ast_type );
+ return return_valobj_sp;
+}
+
+// specialized to work with llvm IR types
+//
+// for now we will specify a default implementation so that we don't need to
+// modify other ABIs
+lldb::ValueObjectSP
+ABI::GetReturnValueObjectImpl( Thread &thread, llvm::Type &ir_type ) const
+{
+ ValueObjectSP return_valobj_sp;
+
+ /* this is a dummy and will only be called if an ABI does not override this */
+
+ return return_valobj_sp;
+}
+bool
+ABI::PrepareTrivialCall (Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::Type &returntype,
+ llvm::ArrayRef<ABI::CallArgument> args) const
+{
+ // dummy prepare trivial call
+ assert( !"Should never get here!" );
+ return false;
+}
diff --git a/source/Target/FileAction.cpp b/source/Target/FileAction.cpp
new file mode 100644
index 000000000000..18b039998bc7
--- /dev/null
+++ b/source/Target/FileAction.cpp
@@ -0,0 +1,95 @@
+//===-- FileAction.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <fcntl.h>
+
+#if defined(_WIN32)
+#include "lldb/Host/Windows/win32.h" // For O_NOCTTY
+#endif
+
+#include "lldb/Target/FileAction.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------------
+// FileAction member functions
+//----------------------------------------------------------------------------
+
+FileAction::FileAction()
+ : m_action(eFileActionNone)
+ , m_fd(-1)
+ , m_arg(-1)
+ , m_path()
+{
+}
+
+void
+FileAction::Clear()
+{
+ m_action = eFileActionNone;
+ m_fd = -1;
+ m_arg = -1;
+ m_path.clear();
+}
+
+const char *
+FileAction::GetPath() const
+{
+ if (m_path.empty())
+ return NULL;
+ return m_path.c_str();
+}
+
+bool
+FileAction::Open(int fd, const char *path, bool read, bool write)
+{
+ if ((read || write) && fd >= 0 && path && path[0])
+ {
+ m_action = eFileActionOpen;
+ m_fd = fd;
+ if (read && write)
+ m_arg = O_NOCTTY | O_CREAT | O_RDWR;
+ else if (read)
+ m_arg = O_NOCTTY | O_RDONLY;
+ else
+ m_arg = O_NOCTTY | O_CREAT | O_WRONLY;
+ m_path.assign(path);
+ return true;
+ }
+ else
+ {
+ Clear();
+ }
+ return false;
+}
+
+bool
+FileAction::Close(int fd)
+{
+ Clear();
+ if (fd >= 0)
+ {
+ m_action = eFileActionClose;
+ m_fd = fd;
+ }
+ return m_fd >= 0;
+}
+
+bool
+FileAction::Duplicate(int fd, int dup_fd)
+{
+ Clear();
+ if (fd >= 0 && dup_fd >= 0)
+ {
+ m_action = eFileActionDuplicate;
+ m_fd = fd;
+ m_arg = dup_fd;
+ }
+ return m_fd >= 0;
+}
diff --git a/source/Target/JITLoader.cpp b/source/Target/JITLoader.cpp
new file mode 100644
index 000000000000..8536d690ece0
--- /dev/null
+++ b/source/Target/JITLoader.cpp
@@ -0,0 +1,38 @@
+//===-- JITLoader.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/JITLoader.h"
+#include "lldb/Target/JITLoaderList.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+JITLoader::LoadPlugins (Process *process, JITLoaderList &list)
+{
+ JITLoaderCreateInstance create_callback = NULL;
+ for (uint32_t idx = 0; (create_callback = PluginManager::GetJITLoaderCreateCallbackAtIndex(idx)) != NULL; ++idx)
+ {
+ JITLoaderSP instance_sp(create_callback(process, false));
+ if (instance_sp)
+ list.Append(std::move(instance_sp));
+ }
+}
+
+JITLoader::JITLoader(Process *process) :
+ m_process (process)
+{
+}
+
+JITLoader::~JITLoader()
+{
+}
diff --git a/source/Target/JITLoaderList.cpp b/source/Target/JITLoaderList.cpp
new file mode 100644
index 000000000000..24a73b7fd516
--- /dev/null
+++ b/source/Target/JITLoaderList.cpp
@@ -0,0 +1,77 @@
+//===-- JITLoader.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/JITLoader.h"
+#include "lldb/Target/JITLoaderList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+JITLoaderList::JITLoaderList()
+ : m_jit_loaders_vec(), m_jit_loaders_mutex(Mutex::eMutexTypeRecursive)
+{
+}
+
+JITLoaderList::~JITLoaderList()
+{
+}
+
+void
+JITLoaderList::Append (const JITLoaderSP &jit_loader_sp)
+{
+ Mutex::Locker locker(m_jit_loaders_mutex);
+ m_jit_loaders_vec.push_back(jit_loader_sp);
+}
+
+void
+JITLoaderList::Remove (const JITLoaderSP &jit_loader_sp)
+{
+ Mutex::Locker locker(m_jit_loaders_mutex);
+ m_jit_loaders_vec.erase(std::remove(m_jit_loaders_vec.begin(),
+ m_jit_loaders_vec.end(), jit_loader_sp),
+ m_jit_loaders_vec.end());
+}
+
+size_t
+JITLoaderList::GetSize() const
+{
+ return m_jit_loaders_vec.size();
+}
+
+JITLoaderSP
+JITLoaderList::GetLoaderAtIndex (size_t idx)
+{
+ Mutex::Locker locker(m_jit_loaders_mutex);
+ return m_jit_loaders_vec[idx];
+}
+
+void
+JITLoaderList::DidLaunch()
+{
+ Mutex::Locker locker(m_jit_loaders_mutex);
+ for (auto const &jit_loader : m_jit_loaders_vec)
+ jit_loader->DidLaunch();
+}
+
+void
+JITLoaderList::DidAttach()
+{
+ Mutex::Locker locker(m_jit_loaders_mutex);
+ for (auto const &jit_loader : m_jit_loaders_vec)
+ jit_loader->DidAttach();
+}
+
+void
+JITLoaderList::ModulesDidLoad(ModuleList &module_list)
+{
+ Mutex::Locker locker(m_jit_loaders_mutex);
+ for (auto const &jit_loader : m_jit_loaders_vec)
+ jit_loader->ModulesDidLoad(module_list);
+}
diff --git a/source/Target/LanguageRuntime.cpp b/source/Target/LanguageRuntime.cpp
index a2b7f1d6ae85..9d48d8b2de7f 100644
--- a/source/Target/LanguageRuntime.cpp
+++ b/source/Target/LanguageRuntime.cpp
@@ -307,6 +307,18 @@ struct language_name_pair language_names[] =
{ "upc", eLanguageTypeUPC },
{ "d", eLanguageTypeD },
{ "python", eLanguageTypePython },
+ { "opencl", eLanguageTypeOpenCL },
+ { "go", eLanguageTypeGo },
+ { "modula3", eLanguageTypeModula3 },
+ { "haskell", eLanguageTypeHaskell },
+ { "c++03", eLanguageTypeC_plus_plus_03 },
+ { "c++11", eLanguageTypeC_plus_plus_11 },
+ { "ocaml", eLanguageTypeOCaml },
+ { "rust", eLanguageTypeRust },
+ { "c11", eLanguageTypeC11 },
+ { "swift", eLanguageTypeSwift },
+ { "julia", eLanguageTypeJulia },
+ { "dylan", eLanguageTypeDylan },
// Now synonyms, in arbitrary order
{ "objc", eLanguageTypeObjC },
{ "objc++", eLanguageTypeObjC_plus_plus }
diff --git a/source/Target/Memory.cpp b/source/Target/Memory.cpp
index 3c8d483f3003..b212fcd23a45 100644
--- a/source/Target/Memory.cpp
+++ b/source/Target/Memory.cpp
@@ -9,6 +9,7 @@
#include "lldb/Target/Memory.h"
// C Includes
+#include <inttypes.h>
// C++ Includes
// Other libraries and framework includes
// Project includes
@@ -119,6 +120,19 @@ MemoryCache::Read (addr_t addr,
Error &error)
{
size_t bytes_left = dst_len;
+
+ // If this memory read request is larger than the cache line size, then
+ // we (1) try to read as much of it at once as possible, and (2) don't
+ // add the data to the memory cache. We don't want to split a big read
+ // up into more separate reads than necessary, and with a large memory read
+ // request, it is unlikely that the caller function will ask for the next
+ // 4 bytes after the large memory read - so there's little benefit to saving
+ // it in the cache.
+ if (dst && dst_len > m_cache_line_byte_size)
+ {
+ return m_process.ReadMemoryFromInferior (addr, dst, dst_len, error);
+ }
+
if (dst && bytes_left > 0)
{
const uint32_t cache_line_byte_size = m_cache_line_byte_size;
@@ -227,16 +241,16 @@ lldb::addr_t
AllocatedBlock::ReserveBlock (uint32_t size)
{
addr_t addr = LLDB_INVALID_ADDRESS;
+ Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
if (size <= m_byte_size)
{
const uint32_t needed_chunks = CalculateChunksNeededForSize (size);
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
if (m_offset_to_chunk_size.empty())
{
m_offset_to_chunk_size[0] = needed_chunks;
if (log)
- log->Printf ("[1] AllocatedBlock::ReserveBlock (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks", 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", this, size, size, 0, needed_chunks, m_chunk_size);
addr = m_addr;
}
else
@@ -254,7 +268,7 @@ AllocatedBlock::ReserveBlock (uint32_t size)
{
m_offset_to_chunk_size[last_offset] = needed_chunks;
if (log)
- log->Printf ("[2] AllocatedBlock::ReserveBlock (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks", size, size, last_offset, needed_chunks, m_chunk_size);
+ 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());
addr = m_addr + last_offset;
break;
}
@@ -270,7 +284,7 @@ AllocatedBlock::ReserveBlock (uint32_t size)
{
m_offset_to_chunk_size[last_offset] = needed_chunks;
if (log)
- log->Printf ("[3] AllocatedBlock::ReserveBlock (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks", size, size, last_offset, needed_chunks, m_chunk_size);
+ 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());
addr = m_addr + last_offset;
break;
}
@@ -329,9 +343,9 @@ AllocatedBlock::ReserveBlock (uint32_t size)
// return m_addr + m_chunk_size * first_chunk_idx;
// }
}
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+
if (log)
- log->Printf ("AllocatedBlock::ReserveBlock (size = %u (0x%x)) => 0x%16.16" PRIx64, size, size, (uint64_t)addr);
+ log->Printf ("AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => 0x%16.16" PRIx64, this, size, size, (uint64_t)addr);
return addr;
}
@@ -348,7 +362,7 @@ AllocatedBlock::FreeBlock (addr_t addr)
}
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
if (log)
- log->Printf ("AllocatedBlock::FreeBlock (addr = 0x%16.16" PRIx64 ") => %i", (uint64_t)addr, success);
+ 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());
return success;
}
@@ -395,8 +409,8 @@ AllocatedMemoryCache::AllocatePage (uint32_t byte_size,
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
{
- log->Printf ("Process::DoAllocateMemory (byte_size = 0x%8.8zx, permissions = %s) => 0x%16.16" PRIx64,
- page_byte_size,
+ log->Printf ("Process::DoAllocateMemory (byte_size = 0x%8.8" PRIx32 ", permissions = %s) => 0x%16.16" PRIx64,
+ (uint32_t)page_byte_size,
GetPermissionsAsCString(permissions),
(uint64_t)addr);
}
@@ -422,6 +436,8 @@ AllocatedMemoryCache::AllocateMemory (size_t byte_size,
for (PermissionsToBlockMap::iterator pos = range.first; pos != range.second; ++pos)
{
addr = (*pos).second->ReserveBlock (byte_size);
+ if (addr != LLDB_INVALID_ADDRESS)
+ break;
}
if (addr == LLDB_INVALID_ADDRESS)
@@ -433,7 +449,7 @@ AllocatedMemoryCache::AllocateMemory (size_t byte_size,
}
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
- log->Printf ("AllocatedMemoryCache::AllocateMemory (byte_size = 0x%8.8zx, permissions = %s) => 0x%16.16" PRIx64, byte_size, GetPermissionsAsCString(permissions), (uint64_t)addr);
+ log->Printf ("AllocatedMemoryCache::AllocateMemory (byte_size = 0x%8.8" PRIx32 ", permissions = %s) => 0x%16.16" PRIx64, (uint32_t)byte_size, GetPermissionsAsCString(permissions), (uint64_t)addr);
return addr;
}
diff --git a/source/Target/NativeRegisterContext.cpp b/source/Target/NativeRegisterContext.cpp
new file mode 100644
index 000000000000..d84e2279a459
--- /dev/null
+++ b/source/Target/NativeRegisterContext.cpp
@@ -0,0 +1,470 @@
+//===-- NativeRegisterContext.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/NativeRegisterContext.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Core/RegisterValue.h"
+
+#include "lldb/lldb-private-log.h"
+
+#include "Host/common/NativeProcessProtocol.h"
+#include "Host/common/NativeThreadProtocol.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+NativeRegisterContext::NativeRegisterContext (NativeThreadProtocol &thread, uint32_t concrete_frame_idx) :
+ m_thread (thread),
+ m_concrete_frame_idx (concrete_frame_idx)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+NativeRegisterContext::~NativeRegisterContext()
+{
+}
+
+// FIXME revisit invalidation, process stop ids, etc. Right now we don't
+// support caching in NativeRegisterContext. We can do this later by
+// utilizing NativeProcessProtocol::GetStopID () and adding a stop id to
+// NativeRegisterContext.
+
+// void
+// NativeRegisterContext::InvalidateIfNeeded (bool force)
+// {
+// ProcessSP process_sp (m_thread.GetProcess());
+// bool invalidate = force;
+// uint32_t process_stop_id = UINT32_MAX;
+
+// if (process_sp)
+// process_stop_id = process_sp->GetStopID();
+// else
+// invalidate = true;
+
+// if (!invalidate)
+// invalidate = process_stop_id != GetStopID();
+
+// if (invalidate)
+// {
+// InvalidateAllRegisters ();
+// SetStopID (process_stop_id);
+// }
+// }
+
+
+const RegisterInfo *
+NativeRegisterContext::GetRegisterInfoByName (const char *reg_name, uint32_t start_idx)
+{
+ if (reg_name && reg_name[0])
+ {
+ const uint32_t num_registers = GetRegisterCount();
+ for (uint32_t reg = start_idx; reg < num_registers; ++reg)
+ {
+ const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg);
+
+ if ((reg_info->name != nullptr && ::strcasecmp (reg_info->name, reg_name) == 0) ||
+ (reg_info->alt_name != nullptr && ::strcasecmp (reg_info->alt_name, reg_name) == 0))
+ {
+ return reg_info;
+ }
+ }
+ }
+ return nullptr;
+}
+
+const RegisterInfo *
+NativeRegisterContext::GetRegisterInfo (uint32_t kind, uint32_t num)
+{
+ const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ return nullptr;
+ return GetRegisterInfoAtIndex (reg_num);
+}
+
+const char *
+NativeRegisterContext::GetRegisterName (uint32_t reg)
+{
+ const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg);
+ if (reg_info)
+ return reg_info->name;
+ return nullptr;
+}
+
+const char*
+NativeRegisterContext::GetRegisterSetNameForRegisterAtIndex (uint32_t reg_index) const
+{
+ const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
+ if (!reg_info)
+ return nullptr;
+
+ for (uint32_t set_index = 0; set_index < GetRegisterSetCount (); ++set_index)
+ {
+ const RegisterSet *const reg_set = GetRegisterSet (set_index);
+ if (!reg_set)
+ continue;
+
+ for (uint32_t reg_num_index = 0; reg_num_index < reg_set->num_registers; ++reg_num_index)
+ {
+ const uint32_t reg_num = reg_set->registers[reg_num_index];
+ // FIXME double check we're checking the right register kind here.
+ if (reg_info->kinds[RegisterKind::eRegisterKindLLDB] == reg_num)
+ {
+ // The given register is a member of this register set. Return the register set name.
+ return reg_set->name;
+ }
+ }
+ }
+
+ // Didn't find it.
+ return nullptr;
+}
+
+lldb::addr_t
+NativeRegisterContext::GetPC (lldb::addr_t fail_value)
+{
+ Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+
+ uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ if (log)
+ log->Printf ("NativeRegisterContext::%s using reg index %" PRIu32 " (default %" PRIu64 ")", __FUNCTION__, reg, fail_value);
+
+ const uint64_t retval = ReadRegisterAsUnsigned (reg, fail_value);
+
+ if (log)
+ log->Printf ("NativeRegisterContext::%s " PRIu32 " retval %" PRIu64, __FUNCTION__, retval);
+
+ return retval;
+}
+
+Error
+NativeRegisterContext::SetPC (lldb::addr_t pc)
+{
+ uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ return WriteRegisterFromUnsigned (reg, pc);
+}
+
+lldb::addr_t
+NativeRegisterContext::GetSP (lldb::addr_t fail_value)
+{
+ uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ return ReadRegisterAsUnsigned (reg, fail_value);
+}
+
+Error
+NativeRegisterContext::SetSP (lldb::addr_t sp)
+{
+ uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ return WriteRegisterFromUnsigned (reg, sp);
+}
+
+lldb::addr_t
+NativeRegisterContext::GetFP (lldb::addr_t fail_value)
+{
+ uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+ return ReadRegisterAsUnsigned (reg, fail_value);
+}
+
+Error
+NativeRegisterContext::SetFP (lldb::addr_t fp)
+{
+ uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+ return WriteRegisterFromUnsigned (reg, fp);
+}
+
+lldb::addr_t
+NativeRegisterContext::GetReturnAddress (lldb::addr_t fail_value)
+{
+ uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+ return ReadRegisterAsUnsigned (reg, fail_value);
+}
+
+lldb::addr_t
+NativeRegisterContext::GetFlags (lldb::addr_t fail_value)
+{
+ uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+ return ReadRegisterAsUnsigned (reg, fail_value);
+}
+
+
+lldb::addr_t
+NativeRegisterContext::ReadRegisterAsUnsigned (uint32_t reg, lldb::addr_t fail_value)
+{
+ if (reg != LLDB_INVALID_REGNUM)
+ return ReadRegisterAsUnsigned (GetRegisterInfoAtIndex (reg), fail_value);
+ return fail_value;
+}
+
+uint64_t
+NativeRegisterContext::ReadRegisterAsUnsigned (const RegisterInfo *reg_info, lldb::addr_t fail_value)
+{
+ Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+
+ if (reg_info)
+ {
+ RegisterValue value;
+ Error error = ReadRegister (reg_info, value);
+ if (error.Success ())
+ {
+ if (log)
+ log->Printf ("NativeRegisterContext::%s ReadRegister() succeeded, value %" PRIu64, __FUNCTION__, value.GetAsUInt64());
+ return value.GetAsUInt64();
+ }
+ else
+ {
+ if (log)
+ log->Printf ("NativeRegisterContext::%s ReadRegister() failed, error %s", __FUNCTION__, error.AsCString ());
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("NativeRegisterContext::%s ReadRegister() null reg_info", __FUNCTION__);
+ }
+ return fail_value;
+}
+
+Error
+NativeRegisterContext::WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval)
+{
+ if (reg == LLDB_INVALID_REGNUM)
+ return Error ("NativeRegisterContext::%s (): reg is invalid", __FUNCTION__);
+ return WriteRegisterFromUnsigned (GetRegisterInfoAtIndex (reg), uval);
+}
+
+Error
+NativeRegisterContext::WriteRegisterFromUnsigned (const RegisterInfo *reg_info, uint64_t uval)
+{
+ assert (reg_info);
+ if (!reg_info)
+ return Error ("reg_info is nullptr");
+
+ RegisterValue value;
+ if (!value.SetUInt(uval, reg_info->byte_size))
+ return Error ("RegisterValue::SetUInt () failed");
+
+ return WriteRegister (reg_info, value);
+}
+
+lldb::tid_t
+NativeRegisterContext::GetThreadID() const
+{
+ return m_thread.GetID();
+}
+
+uint32_t
+NativeRegisterContext::NumSupportedHardwareBreakpoints ()
+{
+ return 0;
+}
+
+uint32_t
+NativeRegisterContext::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
+{
+ return LLDB_INVALID_INDEX32;
+}
+
+bool
+NativeRegisterContext::ClearHardwareBreakpoint (uint32_t hw_idx)
+{
+ return false;
+}
+
+
+uint32_t
+NativeRegisterContext::NumSupportedHardwareWatchpoints ()
+{
+ return 0;
+}
+
+uint32_t
+NativeRegisterContext::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags)
+{
+ return LLDB_INVALID_INDEX32;
+}
+
+bool
+NativeRegisterContext::ClearHardwareWatchpoint (uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+NativeRegisterContext::HardwareSingleStep (bool enable)
+{
+ return false;
+}
+
+Error
+NativeRegisterContext::ReadRegisterValueFromMemory (
+ const RegisterInfo *reg_info,
+ lldb::addr_t src_addr,
+ lldb::addr_t src_len,
+ RegisterValue &reg_value)
+{
+ Error error;
+ if (reg_info == nullptr)
+ {
+ error.SetErrorString ("invalid register info argument.");
+ return error;
+ }
+
+
+ // Moving from addr into a register
+ //
+ // Case 1: src_len == dst_len
+ //
+ // |AABBCCDD| Address contents
+ // |AABBCCDD| Register contents
+ //
+ // Case 2: src_len > dst_len
+ //
+ // Error! (The register should always be big enough to hold the data)
+ //
+ // Case 3: src_len < dst_len
+ //
+ // |AABB| Address contents
+ // |AABB0000| Register contents [on little-endian hardware]
+ // |0000AABB| Register contents [on big-endian hardware]
+ if (src_len > RegisterValue::kMaxRegisterByteSize)
+ {
+ error.SetErrorString ("register too small to receive memory data");
+ return error;
+ }
+
+ const lldb::addr_t dst_len = reg_info->byte_size;
+
+ if (src_len > dst_len)
+ {
+ error.SetErrorStringWithFormat("%" PRIu64 " bytes is too big to store in register %s (%" PRIu64 " bytes)", src_len, reg_info->name, dst_len);
+ return error;
+ }
+
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ {
+ error.SetErrorString("invalid process");
+ return error;
+ }
+
+ uint8_t src[RegisterValue::kMaxRegisterByteSize];
+
+ // Read the memory
+ lldb::addr_t bytes_read;
+ error = process_sp->ReadMemory (src_addr, src, src_len, bytes_read);
+ if (error.Fail ())
+ return error;
+
+ // Make sure the memory read succeeded...
+ if (bytes_read != src_len)
+ {
+ // This might happen if we read _some_ bytes but not all
+ error.SetErrorStringWithFormat("read %" PRIu64 " of %" PRIu64 " bytes", bytes_read, src_len);
+ return error;
+ }
+
+ // We now have a memory buffer that contains the part or all of the register
+ // value. Set the register value using this memory data.
+ // TODO: we might need to add a parameter to this function in case the byte
+ // order of the memory data doesn't match the process. For now we are assuming
+ // they are the same.
+ lldb::ByteOrder byte_order;
+ if (!process_sp->GetByteOrder (byte_order))
+ {
+ error.SetErrorString ( "NativeProcessProtocol::GetByteOrder () failed");
+ return error;
+ }
+
+ reg_value.SetFromMemoryData (
+ reg_info,
+ src,
+ src_len,
+ byte_order,
+ error);
+
+ return error;
+}
+
+Error
+NativeRegisterContext::WriteRegisterValueToMemory (
+ const RegisterInfo *reg_info,
+ lldb::addr_t dst_addr,
+ lldb::addr_t dst_len,
+ const RegisterValue &reg_value)
+{
+
+ uint8_t dst[RegisterValue::kMaxRegisterByteSize];
+
+ Error error;
+
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (process_sp)
+ {
+
+ // TODO: we might need to add a parameter to this function in case the byte
+ // order of the memory data doesn't match the process. For now we are assuming
+ // they are the same.
+ lldb::ByteOrder byte_order;
+ if (!process_sp->GetByteOrder (byte_order))
+ return Error ("NativeProcessProtocol::GetByteOrder () failed");
+
+ const lldb::addr_t bytes_copied = reg_value.GetAsMemoryData (
+ reg_info,
+ dst,
+ dst_len,
+ byte_order,
+ error);
+
+ if (error.Success())
+ {
+ if (bytes_copied == 0)
+ {
+ error.SetErrorString("byte copy failed.");
+ }
+ else
+ {
+ lldb::addr_t bytes_written;
+ error = process_sp->WriteMemory (dst_addr, dst, bytes_copied, bytes_written);
+ if (error.Fail ())
+ return error;
+
+ if (bytes_written != bytes_copied)
+ {
+ // This might happen if we read _some_ bytes but not all
+ error.SetErrorStringWithFormat("only wrote %" PRIu64 " of %" PRIu64 " bytes", bytes_written, bytes_copied);
+ }
+ }
+ }
+ }
+ else
+ error.SetErrorString("invalid process");
+
+ return error;
+}
+
+uint32_t
+NativeRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const
+{
+ 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/Target/NativeRegisterContextRegisterInfo.cpp b/source/Target/NativeRegisterContextRegisterInfo.cpp
new file mode 100644
index 000000000000..e37014546646
--- /dev/null
+++ b/source/Target/NativeRegisterContextRegisterInfo.cpp
@@ -0,0 +1,44 @@
+//===-- NativeRegisterContex.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-types.h"
+#include "lldb/lldb-private-forward.h"
+#include "lldb/Target/NativeRegisterContextRegisterInfo.h"
+
+using namespace lldb_private;
+
+NativeRegisterContextRegisterInfo::NativeRegisterContextRegisterInfo (NativeThreadProtocol &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info_interface) :
+ NativeRegisterContext (thread, concrete_frame_idx),
+ m_register_info_interface_up (register_info_interface)
+{
+ assert (register_info_interface && "null register_info_interface");
+}
+
+uint32_t
+NativeRegisterContextRegisterInfo::GetRegisterCount () const
+{
+ return m_register_info_interface_up->GetRegisterCount ();
+}
+
+const RegisterInfo *
+NativeRegisterContextRegisterInfo::GetRegisterInfoAtIndex (uint32_t reg_index) const
+{
+ if (reg_index <= GetRegisterCount ())
+ return m_register_info_interface_up->GetRegisterInfo () + reg_index;
+ else
+ return nullptr;
+}
+
+const RegisterInfoInterface&
+NativeRegisterContextRegisterInfo::GetRegisterInfoInterface () const
+{
+ return *m_register_info_interface_up;
+}
diff --git a/source/Target/ObjCLanguageRuntime.cpp b/source/Target/ObjCLanguageRuntime.cpp
index 64ddfcc6c796..1f2abd876c84 100644
--- a/source/Target/ObjCLanguageRuntime.cpp
+++ b/source/Target/ObjCLanguageRuntime.cpp
@@ -602,4 +602,27 @@ ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
}
+ClangASTType
+ObjCLanguageRuntime::EncodingToType::RealizeType (const char* name, bool allow_unknownanytype)
+{
+ if (m_scratch_ast_ctx_ap)
+ return RealizeType(*m_scratch_ast_ctx_ap, name, allow_unknownanytype);
+ return ClangASTType();
+}
+
+ClangASTType
+ObjCLanguageRuntime::EncodingToType::RealizeType (ClangASTContext& ast_ctx, const char* name, bool allow_unknownanytype)
+{
+ clang::ASTContext *clang_ast = ast_ctx.getASTContext();
+ if (!clang_ast)
+ return ClangASTType();
+ return RealizeType(*clang_ast, name, allow_unknownanytype);
+}
+
+ObjCLanguageRuntime::EncodingToType::~EncodingToType() {}
+ObjCLanguageRuntime::EncodingToTypeSP
+ObjCLanguageRuntime::GetEncodingToType ()
+{
+ return nullptr;
+}
diff --git a/source/Target/PathMappingList.cpp b/source/Target/PathMappingList.cpp
index db23a0b27130..2fd517829b8c 100644
--- a/source/Target/PathMappingList.cpp
+++ b/source/Target/PathMappingList.cpp
@@ -132,7 +132,7 @@ PathMappingList::Replace (const ConstString &path,
}
bool
-PathMappingList::Remove (off_t index, bool notify)
+PathMappingList::Remove (size_t index, bool notify)
{
if (index >= m_pairs.size())
return false;
@@ -161,7 +161,7 @@ PathMappingList::Dump (Stream *s, int pair_index)
}
else
{
- if (pair_index < numPairs)
+ if (static_cast<unsigned int>(pair_index) < numPairs)
s->Printf("%s -> %s",
m_pairs[pair_index].first.GetCString(), m_pairs[pair_index].second.GetCString());
}
diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp
index d6010fb22a5b..fe73be2d05b9 100644
--- a/source/Target/Platform.cpp
+++ b/source/Target/Platform.cpp
@@ -19,7 +19,9 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Utils.h"
@@ -91,7 +93,7 @@ Platform::GetFileWithUUID (const FileSpec &platform_file,
}
FileSpecList
-Platform::LocateExecutableScriptingResources (Target *target, Module &module)
+Platform::LocateExecutableScriptingResources (Target *target, Module &module, Stream* feedback_stream)
{
return FileSpecList();
}
@@ -257,11 +259,12 @@ Platform::Platform (bool is_host) :
m_ssh_opts (),
m_ignores_remote_hostname (false),
m_trap_handlers(),
- m_calculated_trap_handlers (false)
+ m_calculated_trap_handlers (false),
+ m_trap_handler_mutex()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p Platform::Platform()", this);
+ log->Printf ("%p Platform::Platform()", static_cast<void*>(this));
}
//------------------------------------------------------------------
@@ -274,7 +277,7 @@ Platform::~Platform()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p Platform::~Platform()", this);
+ log->Printf ("%p Platform::~Platform()", static_cast<void*>(this));
}
void
@@ -347,9 +350,7 @@ Platform::GetOSVersion (uint32_t &major,
if (!success)
{
// We have a local host platform
- success = Host::GetOSVersion (m_major_os_version,
- m_minor_os_version,
- m_update_os_version);
+ success = HostInfo::GetOSVersion(m_major_os_version, m_minor_os_version, m_update_os_version);
m_os_version_set_while_connected = success;
}
}
@@ -396,8 +397,14 @@ Platform::GetOSVersion (uint32_t &major,
bool
Platform::GetOSBuildString (std::string &s)
{
+ s.clear();
+
if (IsHost())
- return Host::GetOSBuildString (s);
+#if !defined(__linux__)
+ return HostInfo::GetOSBuildString(s);
+#else
+ return false;
+#endif
else
return GetRemoteOSBuildString (s);
}
@@ -406,7 +413,11 @@ bool
Platform::GetOSKernelDescription (std::string &s)
{
if (IsHost())
- return Host::GetOSKernelDescription (s);
+#if !defined(__linux__)
+ return HostInfo::GetOSKernelDescription(s);
+#else
+ return false;
+#endif
else
return GetRemoteOSKernelDescription (s);
}
@@ -493,8 +504,8 @@ RecurseCopy_Callback (void *baton,
dst_file.GetFilename() = src.GetFilename();
char buf[PATH_MAX];
-
- rc_baton->error = Host::Readlink (src.GetPath().c_str(), buf, sizeof(buf));
+
+ rc_baton->error = FileSystem::Readlink(src.GetPath().c_str(), buf, sizeof(buf));
if (rc_baton->error.Fail())
return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
@@ -526,6 +537,7 @@ 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;
@@ -647,7 +659,7 @@ Platform::Install (const FileSpec& src, const FileSpec& dst)
if (GetFileExists (fixed_dst))
Unlink (fixed_dst.GetPath().c_str());
char buf[PATH_MAX];
- error = Host::Readlink(src.GetPath().c_str(), buf, sizeof(buf));
+ error = FileSystem::Readlink(src.GetPath().c_str(), buf, sizeof(buf));
if (error.Success())
error = CreateSymlink(dst.GetPath().c_str(), buf);
}
@@ -699,7 +711,7 @@ Error
Platform::MakeDirectory (const char *path, uint32_t permissions)
{
if (IsHost())
- return Host::MakeDirectory (path, permissions);
+ return FileSystem::MakeDirectory(path, permissions);
else
{
Error error;
@@ -712,7 +724,7 @@ Error
Platform::GetFilePermissions (const char *path, uint32_t &file_permissions)
{
if (IsHost())
- return Host::GetFilePermissions(path, file_permissions);
+ return FileSystem::GetFilePermissions(path, file_permissions);
else
{
Error error;
@@ -725,7 +737,7 @@ Error
Platform::SetFilePermissions (const char *path, uint32_t file_permissions)
{
if (IsHost())
- return Host::SetFilePermissions(path, file_permissions);
+ return FileSystem::SetFilePermissions(path, file_permissions);
else
{
Error error;
@@ -744,7 +756,7 @@ const char *
Platform::GetHostname ()
{
if (IsHost())
- return "localhost";
+ return "127.0.0.1";
if (m_name.empty())
return NULL;
@@ -764,30 +776,34 @@ Platform::SetRemoteWorkingDirectory(const ConstString &path)
const char *
Platform::GetUserName (uint32_t uid)
{
+#if !defined(LLDB_DISABLE_POSIX)
const char *user_name = GetCachedUserName(uid);
if (user_name)
return user_name;
if (IsHost())
{
std::string name;
- if (Host::GetUserName(uid, name))
+ if (HostInfo::LookupUserName(uid, name))
return SetCachedUserName (uid, name.c_str(), name.size());
}
+#endif
return NULL;
}
const char *
Platform::GetGroupName (uint32_t gid)
{
+#if !defined(LLDB_DISABLE_POSIX)
const char *group_name = GetCachedGroupName(gid);
if (group_name)
return group_name;
if (IsHost())
{
std::string name;
- if (Host::GetGroupName(gid, name))
+ if (HostInfo::LookupGroupName(gid, name))
return SetCachedGroupName (gid, name.c_str(), name.size());
}
+#endif
return NULL;
}
@@ -798,8 +814,8 @@ Platform::SetOSVersion (uint32_t major,
{
if (IsHost())
{
- // We don't need anyone setting the OS version for the host platform,
- // we should be able to figure it out by calling Host::GetOSVersion(...).
+ // We don't need anyone setting the OS version for the host platform,
+ // we should be able to figure it out by calling HostInfo::GetOSVersion(...).
return false;
}
else
@@ -902,7 +918,7 @@ Platform::GetSystemArchitecture()
if (!m_system_arch.IsValid())
{
// We have a local host platform
- m_system_arch = Host::GetArchitecture();
+ m_system_arch = HostInfo::GetArchitecture();
m_system_arch_set_while_connected = m_system_arch.IsValid();
}
}
@@ -1180,11 +1196,32 @@ Platform::CalculateMD5 (const FileSpec& file_spec,
uint64_t &high)
{
if (IsHost())
- return Host::CalculateMD5(file_spec, low, high);
+ return FileSystem::CalculateMD5(file_spec, low, high);
else
return false;
}
+Error
+Platform::LaunchNativeProcess (
+ ProcessLaunchInfo &launch_info,
+ lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
+ NativeProcessProtocolSP &process_sp)
+{
+ // Platforms should override this implementation if they want to
+ // support lldb-gdbserver.
+ return Error("unimplemented");
+}
+
+Error
+Platform::AttachNativeProcess (lldb::pid_t pid,
+ lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
+ NativeProcessProtocolSP &process_sp)
+{
+ // Platforms should override this implementation if they want to
+ // support lldb-gdbserver.
+ return Error("unimplemented");
+}
+
void
Platform::SetLocalCacheDirectory (const char* local)
{
@@ -1200,23 +1237,23 @@ Platform::GetLocalCacheDirectory ()
static OptionDefinition
g_rsync_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "rsync" , 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Enable rsync." },
- { LLDB_OPT_SET_ALL, false, "rsync-opts" , 'R', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName , "Platform-specific options required for rsync to work." },
- { LLDB_OPT_SET_ALL, false, "rsync-prefix" , 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName , "Platform-specific rsync prefix put before the remote path." },
- { LLDB_OPT_SET_ALL, false, "ignore-remote-hostname" , 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Do not automatically fill in the remote hostname when composing the rsync command." },
+ { LLDB_OPT_SET_ALL, false, "rsync" , 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Enable rsync." },
+ { LLDB_OPT_SET_ALL, false, "rsync-opts" , 'R', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName , "Platform-specific options required for rsync to work." },
+ { LLDB_OPT_SET_ALL, false, "rsync-prefix" , 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName , "Platform-specific rsync prefix put before the remote path." },
+ { LLDB_OPT_SET_ALL, false, "ignore-remote-hostname" , 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Do not automatically fill in the remote hostname when composing the rsync command." },
};
static OptionDefinition
g_ssh_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "ssh" , 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Enable SSH." },
- { LLDB_OPT_SET_ALL, false, "ssh-opts" , 'S', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName , "Platform-specific options required for SSH to work." },
+ { LLDB_OPT_SET_ALL, false, "ssh" , 's', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Enable SSH." },
+ { LLDB_OPT_SET_ALL, false, "ssh-opts" , 'S', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName , "Platform-specific options required for SSH to work." },
};
static OptionDefinition
g_caching_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "local-cache-dir" , 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypePath , "Path in which to store local copies of files." },
+ { LLDB_OPT_SET_ALL, false, "local-cache-dir" , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePath , "Path in which to store local copies of files." },
};
OptionGroupPlatformRSync::OptionGroupPlatformRSync ()
@@ -1398,8 +1435,12 @@ Platform::GetTrapHandlerSymbolNames ()
{
if (!m_calculated_trap_handlers)
{
- CalculateTrapHandlerSymbolNames();
- m_calculated_trap_handlers = true;
+ Mutex::Locker locker (m_trap_handler_mutex);
+ if (!m_calculated_trap_handlers)
+ {
+ CalculateTrapHandlerSymbolNames();
+ m_calculated_trap_handlers = true;
+ }
}
return m_trap_handlers;
}
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index 1256ad34c975..a1049787d821 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -27,9 +27,11 @@
#include "lldb/Expression/ClangUserExpression.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/Pipe.h"
#include "lldb/Host/Terminal.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/JITLoader.h"
#include "lldb/Target/OperatingSystem.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/CPPLanguageRuntime.h"
@@ -45,10 +47,6 @@
#include "lldb/Target/ThreadPlanBase.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
-#ifndef LLDB_DISABLE_POSIX
-#include <spawn.h>
-#endif
-
using namespace lldb;
using namespace lldb_private;
@@ -82,7 +80,7 @@ public:
virtual const Property *
GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
{
- // When gettings the value for a key from the process options, we will always
+ // When getting the value for a key from the process options, we will always
// try and grab the setting from the current process if there is one. Else we just
// use the one from this instance.
if (exe_ctx)
@@ -321,8 +319,8 @@ ProcessInstanceInfo::DumpTableHeader (Stream &s, Platform *platform, bool show_a
}
else
{
- s.Printf ("PID PARENT USER ARCH %s\n", label);
- s.PutCString ("====== ====== ========== ======= ============================\n");
+ s.Printf ("PID PARENT USER TRIPLE %s\n", label);
+ s.PutCString ("====== ====== ========== ======================== ============================\n");
}
}
@@ -364,10 +362,9 @@ ProcessInstanceInfo::DumpAsTableRow (Stream &s, Platform *platform, bool show_ar
}
else
{
- s.Printf ("%-10s %-7d %s ",
+ s.Printf ("%-10s %-24s ",
platform->GetUserName (m_euid),
- (int)m_arch.GetTriple().getArchName().size(),
- m_arch.GetTriple().getArchName().data());
+ m_arch.IsValid() ? m_arch.GetTriple().str().c_str() : "");
}
if (verbose || show_args)
@@ -392,361 +389,6 @@ ProcessInstanceInfo::DumpAsTableRow (Stream &s, Platform *platform, bool show_ar
}
}
-
-void
-ProcessInfo::SetArguments (char const **argv, bool first_arg_is_executable)
-{
- m_arguments.SetArguments (argv);
-
- // Is the first argument the executable?
- if (first_arg_is_executable)
- {
- const char *first_arg = m_arguments.GetArgumentAtIndex (0);
- if (first_arg)
- {
- // Yes the first argument is an executable, set it as the executable
- // in the launch options. Don't resolve the file path as the path
- // could be a remote platform path
- const bool resolve = false;
- m_executable.SetFile(first_arg, resolve);
- }
- }
-}
-void
-ProcessInfo::SetArguments (const Args& args, bool first_arg_is_executable)
-{
- // Copy all arguments
- m_arguments = args;
-
- // Is the first argument the executable?
- if (first_arg_is_executable)
- {
- const char *first_arg = m_arguments.GetArgumentAtIndex (0);
- if (first_arg)
- {
- // Yes the first argument is an executable, set it as the executable
- // in the launch options. Don't resolve the file path as the path
- // could be a remote platform path
- const bool resolve = false;
- m_executable.SetFile(first_arg, resolve);
- }
- }
-}
-
-void
-ProcessLaunchInfo::FinalizeFileActions (Target *target, bool default_to_use_pty)
-{
- // If notthing was specified, then check the process for any default
- // settings that were set with "settings set"
- if (m_file_actions.empty())
- {
- if (m_flags.Test(eLaunchFlagDisableSTDIO))
- {
- AppendSuppressFileAction (STDIN_FILENO , true, false);
- AppendSuppressFileAction (STDOUT_FILENO, false, true);
- AppendSuppressFileAction (STDERR_FILENO, false, true);
- }
- else
- {
- // Check for any values that might have gotten set with any of:
- // (lldb) settings set target.input-path
- // (lldb) settings set target.output-path
- // (lldb) settings set target.error-path
- FileSpec in_path;
- FileSpec out_path;
- FileSpec err_path;
- if (target)
- {
- in_path = target->GetStandardInputPath();
- out_path = target->GetStandardOutputPath();
- err_path = target->GetStandardErrorPath();
- }
-
- if (in_path || out_path || err_path)
- {
- char path[PATH_MAX];
- if (in_path && in_path.GetPath(path, sizeof(path)))
- AppendOpenFileAction(STDIN_FILENO, path, true, false);
-
- if (out_path && out_path.GetPath(path, sizeof(path)))
- AppendOpenFileAction(STDOUT_FILENO, path, false, true);
-
- if (err_path && err_path.GetPath(path, sizeof(path)))
- AppendOpenFileAction(STDERR_FILENO, path, false, true);
- }
- else if (default_to_use_pty)
- {
- if (m_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, NULL, 0))
- {
- const char *slave_path = m_pty.GetSlaveName (NULL, 0);
- AppendOpenFileAction(STDIN_FILENO, slave_path, true, false);
- AppendOpenFileAction(STDOUT_FILENO, slave_path, false, true);
- AppendOpenFileAction(STDERR_FILENO, slave_path, false, true);
- }
- }
- }
- }
-}
-
-
-bool
-ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error,
- bool localhost,
- bool will_debug,
- bool first_arg_is_full_shell_command,
- int32_t num_resumes)
-{
- error.Clear();
-
- if (GetFlags().Test (eLaunchFlagLaunchInShell))
- {
- const char *shell_executable = GetShell();
- if (shell_executable)
- {
- 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;
- }
-
- 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");
- StreamString shell_command;
- if (will_debug)
- {
- // Add a modified PATH environment variable in case argv[0]
- // is a relative path
- const char *argv0 = argv[0];
- if (argv0 && (argv0[0] != '/' && argv0[0] != '~'))
- {
- // 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")
- const char *working_dir = GetWorkingDirectory();
- // Be sure to put quotes around PATH's value in case any paths have spaces...
- std::string new_path("PATH=\"");
- const size_t empty_path_len = new_path.size();
-
- if (working_dir && working_dir[0])
- {
- new_path += working_dir;
- }
- else
- {
- char current_working_dir[PATH_MAX];
- const char *cwd = getcwd(current_working_dir, sizeof(current_working_dir));
- if (cwd && cwd[0])
- new_path += cwd;
- }
- const char *curr_path = getenv("PATH");
- if (curr_path)
- {
- if (new_path.size() > empty_path_len)
- new_path += ':';
- new_path += curr_path;
- }
- new_path += "\" ";
- shell_command.PutCString(new_path.c_str());
- }
-
- shell_command.PutCString ("exec");
-
- // Only Apple supports /usr/bin/arch being able to specify the architecture
- if (GetArchitecture().IsValid())
- {
- shell_command.Printf(" /usr/bin/arch -arch %s", GetArchitecture().GetArchitectureName());
- // Set the resume count to 2:
- // 1 - stop in shell
- // 2 - stop in /usr/bin/arch
- // 3 - then we will stop in our program
- SetResumeCount(num_resumes + 1);
- }
- else
- {
- // Set the resume count to 1:
- // 1 - stop in shell
- // 2 - then we will stop in our program
- SetResumeCount(num_resumes);
- }
- }
-
- if (first_arg_is_full_shell_command)
- {
- // There should only be one argument that is the shell command itself to be used as is
- if (argv[0] && !argv[1])
- shell_command.Printf("%s", argv[0]);
- else
- return false;
- }
- else
- {
- for (size_t i=0; argv[i] != NULL; ++i)
- {
- const char *arg = Args::GetShellSafeArgument (argv[i], safe_arg);
- shell_command.Printf(" %s", arg);
- }
- }
- shell_arguments.AppendArgument (shell_command.GetString().c_str());
- m_executable.SetFile(shell_executable, false);
- m_arguments = shell_arguments;
- return true;
- }
- else
- {
- error.SetErrorString ("invalid shell path");
- }
- }
- else
- {
- error.SetErrorString ("not launching in shell");
- }
- return false;
-}
-
-
-bool
-ProcessLaunchInfo::FileAction::Open (int fd, const char *path, bool read, bool write)
-{
- if ((read || write) && fd >= 0 && path && path[0])
- {
- m_action = eFileActionOpen;
- m_fd = fd;
- if (read && write)
- m_arg = O_NOCTTY | O_CREAT | O_RDWR;
- else if (read)
- m_arg = O_NOCTTY | O_RDONLY;
- else
- m_arg = O_NOCTTY | O_CREAT | O_WRONLY;
- m_path.assign (path);
- return true;
- }
- else
- {
- Clear();
- }
- return false;
-}
-
-bool
-ProcessLaunchInfo::FileAction::Close (int fd)
-{
- Clear();
- if (fd >= 0)
- {
- m_action = eFileActionClose;
- m_fd = fd;
- }
- return m_fd >= 0;
-}
-
-
-bool
-ProcessLaunchInfo::FileAction::Duplicate (int fd, int dup_fd)
-{
- Clear();
- if (fd >= 0 && dup_fd >= 0)
- {
- m_action = eFileActionDuplicate;
- m_fd = fd;
- m_arg = dup_fd;
- }
- return m_fd >= 0;
-}
-
-
-
-#ifndef LLDB_DISABLE_POSIX
-bool
-ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (void *_file_actions,
- const FileAction *info,
- Log *log,
- Error& error)
-{
- if (info == NULL)
- return false;
-
- posix_spawn_file_actions_t *file_actions = reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions);
-
- switch (info->m_action)
- {
- case eFileActionNone:
- error.Clear();
- break;
-
- case eFileActionClose:
- if (info->m_fd == -1)
- error.SetErrorString ("invalid fd for posix_spawn_file_actions_addclose(...)");
- else
- {
- error.SetError (::posix_spawn_file_actions_addclose (file_actions, info->m_fd),
- eErrorTypePOSIX);
- if (log && (error.Fail() || log))
- error.PutToLog(log, "posix_spawn_file_actions_addclose (action=%p, fd=%i)",
- file_actions, info->m_fd);
- }
- break;
-
- case eFileActionDuplicate:
- if (info->m_fd == -1)
- error.SetErrorString ("invalid fd for posix_spawn_file_actions_adddup2(...)");
- else if (info->m_arg == -1)
- error.SetErrorString ("invalid duplicate fd for posix_spawn_file_actions_adddup2(...)");
- else
- {
- error.SetError (::posix_spawn_file_actions_adddup2 (file_actions, info->m_fd, info->m_arg),
- eErrorTypePOSIX);
- if (log && (error.Fail() || log))
- error.PutToLog(log, "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)",
- file_actions, info->m_fd, info->m_arg);
- }
- break;
-
- case eFileActionOpen:
- if (info->m_fd == -1)
- error.SetErrorString ("invalid fd in posix_spawn_file_actions_addopen(...)");
- else
- {
- int oflag = info->m_arg;
-
- mode_t mode = 0;
-
- if (oflag & O_CREAT)
- mode = 0640;
-
- error.SetError (::posix_spawn_file_actions_addopen (file_actions,
- info->m_fd,
- info->m_path.c_str(),
- oflag,
- mode),
- eErrorTypePOSIX);
- if (error.Fail() || log)
- error.PutToLog(log,
- "posix_spawn_file_actions_addopen (action=%p, fd=%i, path='%s', oflag=%i, mode=%i)",
- file_actions, info->m_fd, info->m_path.c_str(), oflag, mode);
- }
- break;
- }
- return error.Success();
-}
-#endif
-
Error
ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
{
@@ -760,45 +402,44 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op
break;
case 'i': // STDIN for read only
- {
- ProcessLaunchInfo::FileAction action;
- if (action.Open (STDIN_FILENO, option_arg, true, false))
- launch_info.AppendFileAction (action);
- }
+ {
+ FileAction action;
+ if (action.Open (STDIN_FILENO, option_arg, true, false))
+ launch_info.AppendFileAction (action);
break;
+ }
case 'o': // Open STDOUT for write only
- {
- ProcessLaunchInfo::FileAction action;
- if (action.Open (STDOUT_FILENO, option_arg, false, true))
- launch_info.AppendFileAction (action);
- }
+ {
+ FileAction action;
+ if (action.Open (STDOUT_FILENO, option_arg, false, true))
+ launch_info.AppendFileAction (action);
break;
+ }
case 'e': // STDERR for write only
- {
- ProcessLaunchInfo::FileAction action;
- if (action.Open (STDERR_FILENO, option_arg, false, true))
- launch_info.AppendFileAction (action);
- }
+ {
+ FileAction action;
+ if (action.Open (STDERR_FILENO, option_arg, false, true))
+ launch_info.AppendFileAction (action);
break;
-
+ }
case 'p': // Process plug-in name
launch_info.SetProcessPluginName (option_arg);
break;
case 'n': // Disable STDIO
- {
- ProcessLaunchInfo::FileAction action;
- if (action.Open (STDIN_FILENO, "/dev/null", true, false))
- launch_info.AppendFileAction (action);
- if (action.Open (STDOUT_FILENO, "/dev/null", false, true))
- launch_info.AppendFileAction (action);
- if (action.Open (STDERR_FILENO, "/dev/null", false, true))
- launch_info.AppendFileAction (action);
- }
+ {
+ FileAction action;
+ if (action.Open (STDIN_FILENO, "/dev/null", true, false))
+ launch_info.AppendFileAction (action);
+ if (action.Open (STDOUT_FILENO, "/dev/null", false, true))
+ launch_info.AppendFileAction (action);
+ if (action.Open (STDERR_FILENO, "/dev/null", false, true))
+ launch_info.AppendFileAction (action);
break;
+ }
case 'w':
launch_info.SetWorkingDirectory (option_arg);
@@ -813,11 +454,18 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op
launch_info.GetArchitecture().SetTriple (option_arg);
break;
- case 'A':
- launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
+ case 'A': // Disable ASLR.
+ {
+ bool success;
+ const bool disable_aslr_arg = Args::StringToBoolean (option_arg, true, &success);
+ if (success)
+ disable_aslr = disable_aslr_arg ? eLazyBoolYes : eLazyBoolNo;
+ else
+ error.SetErrorStringWithFormat ("Invalid boolean value for disable-aslr option: '%s'", option_arg ? option_arg : "<null>");
break;
-
- case 'c':
+ }
+
+ case 'c':
if (option_arg && option_arg[0])
launch_info.SetShell (option_arg);
else
@@ -831,7 +479,6 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op
default:
error.SetErrorStringWithFormat("unrecognized short option character '%c'", short_option);
break;
-
}
return error;
}
@@ -839,23 +486,23 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op
OptionDefinition
ProcessLaunchCommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
-{ LLDB_OPT_SET_ALL, false, "disable-aslr", 'A', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Disable address space layout randomization when launching a process."},
-{ LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
-{ LLDB_OPT_SET_ALL, false, "working-dir", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."},
-{ LLDB_OPT_SET_ALL, false, "arch", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeArchitecture, "Set the architecture for the process to launch when ambiguous."},
-{ LLDB_OPT_SET_ALL, false, "environment", 'v', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone, "Specify an environment variable name/value string (--environment NAME=VALUE). Can be specified multiple times for subsequent environment entries."},
-{ LLDB_OPT_SET_ALL, false, "shell", 'c', OptionParser::eOptionalArgument, NULL, 0, eArgTypeFilename, "Run the process in a shell (not supported on all platforms)."},
+{ LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
+{ LLDB_OPT_SET_ALL, false, "disable-aslr", 'A', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Set whether to disable address space layout randomization when launching a process."},
+{ LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
+{ LLDB_OPT_SET_ALL, false, "working-dir", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."},
+{ LLDB_OPT_SET_ALL, false, "arch", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeArchitecture, "Set the architecture for the process to launch when ambiguous."},
+{ LLDB_OPT_SET_ALL, false, "environment", 'v', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone, "Specify an environment variable name/value string (--environment NAME=VALUE). Can be specified multiple times for subsequent environment entries."},
+{ LLDB_OPT_SET_ALL, false, "shell", 'c', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeFilename, "Run the process in a shell (not supported on all platforms)."},
-{ LLDB_OPT_SET_1 , false, "stdin", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Redirect stdin for the process to <filename>."},
-{ LLDB_OPT_SET_1 , false, "stdout", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Redirect stdout for the process to <filename>."},
-{ LLDB_OPT_SET_1 , false, "stderr", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Redirect stderr for the process to <filename>."},
+{ LLDB_OPT_SET_1 , false, "stdin", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Redirect stdin for the process to <filename>."},
+{ LLDB_OPT_SET_1 , false, "stdout", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Redirect stdout for the process to <filename>."},
+{ LLDB_OPT_SET_1 , false, "stderr", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Redirect stderr for the process to <filename>."},
-{ LLDB_OPT_SET_2 , false, "tty", 't', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Start the process in a terminal (not supported on all platforms)."},
+{ LLDB_OPT_SET_2 , false, "tty", 't', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Start the process in a terminal (not supported on all platforms)."},
-{ LLDB_OPT_SET_3 , false, "no-stdio", 'n', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
+{ LLDB_OPT_SET_3 , false, "no-stdio", 'n', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
-{ 0 , false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+{ 0 , false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -1006,6 +653,13 @@ Process::GetStaticBroadcasterClass ()
// Process constructor
//----------------------------------------------------------------------
Process::Process(Target &target, Listener &listener) :
+ Process(target, listener, Host::GetUnixSignals ())
+{
+ // This constructor just delegates to the full Process constructor,
+ // defaulting to using the Host's UnixSignals.
+}
+
+Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_signals_sp) :
ProcessProperties (false),
UserID (LLDB_INVALID_PROCESS_ID),
Broadcaster (&(target.GetDebugger()), "lldb.process"),
@@ -1035,7 +689,7 @@ Process::Process(Target &target, Listener &listener) :
m_listener (listener),
m_breakpoint_site_list (),
m_dynamic_checkers_ap (),
- m_unix_signals (),
+ m_unix_signals_sp (unix_signals_sp),
m_abi_sp (),
m_process_input_reader (),
m_stdio_communication ("process.stdio"),
@@ -1044,6 +698,7 @@ Process::Process(Target &target, Listener &listener) :
m_stderr_data (),
m_profile_data_comm_mutex (Mutex::eMutexTypeRecursive),
m_profile_data (),
+ m_iohandler_sync (false),
m_memory_cache (*this),
m_allocated_memory_cache (*this),
m_should_detach (false),
@@ -1062,7 +717,10 @@ Process::Process(Target &target, Listener &listener) :
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p Process::Process()", this);
+ log->Printf ("%p Process::Process()", static_cast<void*>(this));
+
+ if (!m_unix_signals_sp)
+ m_unix_signals_sp.reset (new UnixSignals ());
SetEventName (eBroadcastBitStateChanged, "state-changed");
SetEventName (eBroadcastBitInterrupt, "interrupt");
@@ -1089,6 +747,8 @@ Process::Process(Target &target, Listener &listener) :
eBroadcastInternalStateControlStop |
eBroadcastInternalStateControlPause |
eBroadcastInternalStateControlResume);
+ // We need something valid here, even if just the default UnixSignalsSP.
+ assert (m_unix_signals_sp && "null m_unix_signals_sp after initialization");
}
//----------------------------------------------------------------------
@@ -1098,7 +758,7 @@ Process::~Process()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p Process::~Process()", this);
+ log->Printf ("%p Process::~Process()", static_cast<void*>(this));
StopPrivateStateThread();
}
@@ -1154,6 +814,7 @@ Process::Finalize()
m_os_ap.reset();
m_system_runtime_ap.reset();
m_dyld_ap.reset();
+ m_jit_loaders_ap.reset();
m_thread_list_real.Destroy();
m_thread_list.Destroy();
m_extended_thread_list.Destroy();
@@ -1241,6 +902,34 @@ Process::GetNextEvent (EventSP &event_sp)
return state;
}
+bool
+Process::SyncIOHandler (uint64_t timeout_msec)
+{
+ bool timed_out = false;
+
+ // don't sync (potentially context switch) in case where there is no process IO
+ if (m_process_input_reader)
+ {
+ TimeValue timeout = TimeValue::Now();
+ timeout.OffsetWithMicroSeconds(timeout_msec*1000);
+
+ m_iohandler_sync.WaitForValueEqualTo(true, &timeout, &timed_out);
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ if(log)
+ {
+ if(timed_out)
+ log->Printf ("Process::%s pid %" PRIu64 " (timeout=%" PRIu64 "ms): FAIL", __FUNCTION__, GetID (), timeout_msec);
+ else
+ log->Printf ("Process::%s pid %" PRIu64 ": SUCCESS", __FUNCTION__, GetID ());
+ }
+
+ // reset sync one-shot so it will be ready for next time
+ m_iohandler_sync.SetValue(false, eBroadcastNever);
+ }
+
+ return !timed_out;
+}
StateType
Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr, bool wait_always, Listener *hijack_listener)
@@ -1258,7 +947,8 @@ Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
- log->Printf ("Process::%s (timeout = %p)", __FUNCTION__, timeout);
+ log->Printf ("Process::%s (timeout = %p)", __FUNCTION__,
+ static_cast<const void*>(timeout));
if (!wait_always &&
StateIsStoppedState(state, true) &&
@@ -1375,12 +1065,13 @@ Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp,
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
- log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__, timeout);
+ log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__,
+ static_cast<const void*>(timeout));
Listener *listener = hijack_listener;
if (listener == NULL)
listener = &m_listener;
-
+
StateType state = eStateInvalid;
if (listener->WaitForEventForBroadcasterWithType (timeout,
this,
@@ -1395,8 +1086,7 @@ Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp,
if (log)
log->Printf ("Process::%s (timeout = %p, event_sp) => %s",
- __FUNCTION__,
- timeout,
+ __FUNCTION__, static_cast<const void*>(timeout),
StateAsCString(state));
return state;
}
@@ -1435,7 +1125,8 @@ Process::WaitForStateChangedEventsPrivate (const TimeValue *timeout, EventSP &ev
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
- log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__, timeout);
+ log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__,
+ static_cast<const void*>(timeout));
StateType state = eStateInvalid;
if (m_private_state_listener.WaitForEventForBroadcasterWithType (timeout,
@@ -1449,12 +1140,9 @@ Process::WaitForStateChangedEventsPrivate (const TimeValue *timeout, EventSP &ev
// to the command-line, and that could disable the log, which would render the
// log we got above invalid.
if (log)
- {
- if (state == eStateInvalid)
- log->Printf ("Process::%s (timeout = %p, event_sp) => TIMEOUT", __FUNCTION__, timeout);
- else
- log->Printf ("Process::%s (timeout = %p, event_sp) => %s", __FUNCTION__, timeout, StateAsCString(state));
- }
+ log->Printf ("Process::%s (timeout = %p, event_sp) => %s",
+ __FUNCTION__, static_cast<const void *>(timeout),
+ state == eStateInvalid ? "TIMEOUT" : StateAsCString(state));
return state;
}
@@ -1464,7 +1152,8 @@ Process::WaitForEventsPrivate (const TimeValue *timeout, EventSP &event_sp, bool
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
- log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__, timeout);
+ log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__,
+ static_cast<const void*>(timeout));
if (control_only)
return m_private_state_listener.WaitForEventForBroadcaster(timeout, &m_private_state_control_broadcaster, event_sp);
@@ -1523,12 +1212,11 @@ Process::SetExitStatus (int status, const char *cstr)
DidExit ();
SetPrivateState (eStateExited);
- CancelWatchForSTDIN (true);
return true;
}
// This static callback can be used to watch for local child processes on
-// the current host. The the child process exits, the process will be
+// the current host. The child process exits, the process will be
// found in the global target list (we want to be completely sure that the
// lldb_private::Process doesn't go away before we can deliver the signal.
bool
@@ -1766,6 +1454,9 @@ Process::GetPrivateState ()
void
Process::SetPrivateState (StateType new_state)
{
+ if (m_finalize_called)
+ return;
+
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS));
bool state_changed = false;
@@ -1874,9 +1565,27 @@ Process::LoadImage (const FileSpec &image_spec, Error &error)
expr_options.SetUnwindOnError(true);
expr_options.SetIgnoreBreakpoints(true);
expr_options.SetExecutionPolicy(eExecutionPolicyAlways);
+ expr_options.SetResultIsInternal(true);
+
StreamString expr;
- expr.Printf("dlopen (\"%s\", 2)", path);
- const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
+ expr.Printf(R"(
+ struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result;
+ the_result.image_ptr = dlopen ("%s", 2);
+ if (the_result.image_ptr == (void *) 0x0)
+ {
+ the_result.error_str = dlerror();
+ }
+ else
+ {
+ the_result.error_str = (const char *) 0x0;
+ }
+ the_result;
+ )",
+ path);
+ const char *prefix = R"(
+ extern "C" void* dlopen (const char *path, int mode);
+ extern "C" const char *dlerror (void);
+ )";
lldb::ValueObjectSP result_valobj_sp;
Error expr_error;
ClangUserExpression::Evaluate (exe_ctx,
@@ -1891,7 +1600,8 @@ Process::LoadImage (const FileSpec &image_spec, Error &error)
if (error.Success())
{
Scalar scalar;
- if (result_valobj_sp->ResolveValue (scalar))
+ ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true);
+ if (image_ptr_sp && image_ptr_sp->ResolveValue (scalar))
{
addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS)
@@ -1900,9 +1610,28 @@ Process::LoadImage (const FileSpec &image_spec, Error &error)
m_image_tokens.push_back (image_ptr);
return image_token;
}
+ else if (image_ptr == 0)
+ {
+ ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true);
+ if (error_str_sp)
+ {
+ if (error_str_sp->IsCStringContainer(true))
+ {
+ StreamString s;
+ size_t num_chars = error_str_sp->ReadPointedString (s, error);
+ if (error.Success() && num_chars > 0)
+ {
+ error.Clear();
+ error.SetErrorStringWithFormat("dlopen error: %s", s.GetData());
+ }
+ }
+ }
+ }
}
}
}
+ else
+ error = expr_error;
}
}
}
@@ -2169,7 +1898,7 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw
symbol->GetAddress().GetLoadAddress(&m_target),
owner->GetBreakpoint().GetID(),
owner->GetID(),
- error.AsCString() ? error.AsCString() : "unkown error");
+ error.AsCString() ? error.AsCString() : "unknown error");
return LLDB_INVALID_BREAK_ID;
}
Address resolved_address(load_addr);
@@ -2217,7 +1946,7 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw
load_addr,
owner->GetBreakpoint().GetID(),
owner->GetID(),
- error.AsCString() ? error.AsCString() : "unkown error");
+ error.AsCString() ? error.AsCString() : "unknown error");
}
}
}
@@ -2379,7 +2108,7 @@ Process::DisableSoftwareBreakpoint (BreakpointSite *bp_site)
const uint8_t * const break_op = bp_site->GetTrapOpcodeBytes();
if (break_op_size > 0)
{
- // Clear a software breakoint instruction
+ // Clear a software breakpoint instruction
uint8_t curr_break_op[8];
assert (break_op_size <= sizeof(curr_break_op));
bool break_op_found = false;
@@ -2881,6 +2610,7 @@ Process::CanJIT ()
{
if (m_can_jit == eCanJITDontKnow)
{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
Error err;
uint64_t allocated_memory = AllocateMemory(8,
@@ -2888,9 +2618,17 @@ Process::CanJIT ()
err);
if (err.Success())
+ {
m_can_jit = eCanJITYes;
+ if (log)
+ log->Printf ("Process::%s pid %" PRIu64 " allocation test passed, CanJIT () is true", __FUNCTION__, GetID ());
+ }
else
+ {
m_can_jit = eCanJITNo;
+ if (log)
+ log->Printf ("Process::%s pid %" PRIu64 " allocation test failed, CanJIT () is false: %s", __FUNCTION__, GetID (), err.AsCString ());
+ }
DeallocateMemory (allocated_memory);
}
@@ -2930,13 +2668,14 @@ Process::DeallocateMemory (addr_t ptr)
ModuleSP
Process::ReadModuleFromMemory (const FileSpec& file_spec,
- lldb::addr_t header_addr)
+ lldb::addr_t header_addr,
+ size_t size_to_read)
{
ModuleSP module_sp (new Module (file_spec, ArchSpec()));
if (module_sp)
{
Error error;
- ObjectFile *objfile = module_sp->GetMemoryObjectFile (shared_from_this(), header_addr, error);
+ ObjectFile *objfile = module_sp->GetMemoryObjectFile (shared_from_this(), header_addr, error, size_to_read);
if (objfile)
return module_sp;
}
@@ -2989,6 +2728,7 @@ Process::Launch (ProcessLaunchInfo &launch_info)
Error error;
m_abi_sp.reset();
m_dyld_ap.reset();
+ m_jit_loaders_ap.reset();
m_system_runtime_ap.reset();
m_os_ap.reset();
m_process_input_reader.reset();
@@ -3065,6 +2805,8 @@ Process::Launch (ProcessLaunchInfo &launch_info)
if (dyld)
dyld->DidLaunch();
+ GetJITLoaders().DidLaunch();
+
SystemRuntime *system_runtime = GetSystemRuntime ();
if (system_runtime)
system_runtime->DidLaunch();
@@ -3111,6 +2853,8 @@ Process::LoadCore ()
DynamicLoader *dyld = GetDynamicLoader ();
if (dyld)
dyld->DidAttach();
+
+ GetJITLoaders().DidAttach();
SystemRuntime *system_runtime = GetSystemRuntime ();
if (system_runtime)
@@ -3134,6 +2878,23 @@ Process::GetDynamicLoader ()
return m_dyld_ap.get();
}
+const lldb::DataBufferSP
+Process::GetAuxvData()
+{
+ return DataBufferSP ();
+}
+
+JITLoaderList &
+Process::GetJITLoaders ()
+{
+ if (!m_jit_loaders_ap)
+ {
+ m_jit_loaders_ap.reset(new JITLoaderList());
+ JITLoader::LoadPlugins(this, *m_jit_loaders_ap);
+ }
+ return *m_jit_loaders_ap;
+}
+
SystemRuntime *
Process::GetSystemRuntime ()
{
@@ -3142,12 +2903,25 @@ Process::GetSystemRuntime ()
return m_system_runtime_ap.get();
}
+Process::AttachCompletionHandler::AttachCompletionHandler (Process *process, uint32_t exec_count) :
+ NextEventAction (process),
+ m_exec_count (exec_count)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf ("Process::AttachCompletionHandler::%s process=%p, exec_count=%" PRIu32, __FUNCTION__, static_cast<void*>(process), exec_count);
+}
Process::NextEventAction::EventActionResult
Process::AttachCompletionHandler::PerformAction (lldb::EventSP &event_sp)
{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+
StateType state = ProcessEventData::GetStateFromEvent (event_sp.get());
- switch (state)
+ if (log)
+ log->Printf ("Process::AttachCompletionHandler::%s called with state %s (%d)", __FUNCTION__, StateAsCString(state), static_cast<int> (state));
+
+ switch (state)
{
case eStateRunning:
case eStateConnected:
@@ -3165,11 +2939,18 @@ Process::AttachCompletionHandler::PerformAction (lldb::EventSP &event_sp)
if (m_exec_count > 0)
{
--m_exec_count;
+
+ if (log)
+ log->Printf ("Process::AttachCompletionHandler::%s state %s: reduced remaining exec count to %" PRIu32 ", requesting resume", __FUNCTION__, StateAsCString(state), m_exec_count);
+
RequestResume();
return eEventActionRetry;
}
else
{
+ if (log)
+ log->Printf ("Process::AttachCompletionHandler::%s state %s: no more execs expected to start, continuing with attach", __FUNCTION__, StateAsCString(state));
+
m_process->CompleteAttach ();
return eEventActionSuccess;
}
@@ -3204,6 +2985,7 @@ Process::Attach (ProcessAttachInfo &attach_info)
m_abi_sp.reset();
m_process_input_reader.reset();
m_dyld_ap.reset();
+ m_jit_loaders_ap.reset();
m_system_runtime_ap.reset();
m_os_ap.reset();
@@ -3276,7 +3058,17 @@ Process::Attach (ProcessAttachInfo &attach_info)
{
match_info.GetProcessInfo().GetExecutableFile().GetPath (process_name, sizeof(process_name));
if (num_matches > 1)
- error.SetErrorStringWithFormat ("more than one process named %s", process_name);
+ {
+ StreamString s;
+ ProcessInstanceInfo::DumpTableHeader (s, platform_sp.get(), true, false);
+ for (size_t i = 0; i < num_matches; i++)
+ {
+ process_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(s, platform_sp.get(), true, false);
+ }
+ error.SetErrorStringWithFormat ("more than one process named %s:\n%s",
+ process_name,
+ s.GetData());
+ }
else
error.SetErrorStringWithFormat ("could not find a process named %s", process_name);
}
@@ -3340,9 +3132,26 @@ Process::Attach (ProcessAttachInfo &attach_info)
void
Process::CompleteAttach ()
{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf ("Process::%s()", __FUNCTION__);
+
// Let the process subclass figure out at much as it can about the process
// before we go looking for a dynamic loader plug-in.
- DidAttach();
+ ArchSpec process_arch;
+ DidAttach(process_arch);
+
+ if (process_arch.IsValid())
+ {
+ m_target.SetArchitecture(process_arch);
+ if (log)
+ {
+ const char *triple_str = process_arch.GetTriple().getTriple().c_str ();
+ log->Printf ("Process::%s replacing process architecture with DidAttach() architecture: %s",
+ __FUNCTION__,
+ triple_str ? triple_str : "<null>");
+ }
+ }
// We just attached. If we have a platform, ask it for the process architecture, and if it isn't
// the same as the one we've already set, switch architectures.
@@ -3359,15 +3168,21 @@ Process::CompleteAttach ()
{
m_target.SetPlatform (platform_sp);
m_target.SetArchitecture(platform_arch);
+ if (log)
+ log->Printf ("Process::%s switching platform to %s and architecture to %s based on info from attach", __FUNCTION__, platform_sp->GetName().AsCString (""), platform_arch.GetTriple().getTriple().c_str ());
}
}
- else
+ else if (!process_arch.IsValid())
{
ProcessInstanceInfo process_info;
platform_sp->GetProcessInfo (GetID(), process_info);
const ArchSpec &process_arch = process_info.GetArchitecture();
if (process_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(process_arch))
+ {
m_target.SetArchitecture (process_arch);
+ if (log)
+ log->Printf ("Process::%s switching architecture to %s based on info the platform retrieved for pid %" PRIu64, __FUNCTION__, process_arch.GetTriple().getTriple().c_str (), GetID ());
+ }
}
}
@@ -3375,11 +3190,33 @@ Process::CompleteAttach ()
// plug-in
DynamicLoader *dyld = GetDynamicLoader ();
if (dyld)
+ {
dyld->DidAttach();
+ if (log)
+ {
+ ModuleSP exe_module_sp = m_target.GetExecutableModule ();
+ log->Printf ("Process::%s after DynamicLoader::DidAttach(), target executable is %s (using %s plugin)",
+ __FUNCTION__,
+ exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>",
+ dyld->GetPluginName().AsCString ("<unnamed>"));
+ }
+ }
+
+ GetJITLoaders().DidAttach();
SystemRuntime *system_runtime = GetSystemRuntime ();
if (system_runtime)
+ {
system_runtime->DidAttach();
+ if (log)
+ {
+ ModuleSP exe_module_sp = m_target.GetExecutableModule ();
+ log->Printf ("Process::%s after SystemRuntime::DidAttach(), target executable is %s (using %s plugin)",
+ __FUNCTION__,
+ exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>",
+ system_runtime->GetPluginName().AsCString("<unnamed>"));
+ }
+ }
m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
// Figure out which one is the executable, and set that in our target:
@@ -3399,7 +3236,16 @@ Process::CompleteAttach ()
}
}
if (new_executable_module_sp)
+ {
m_target.SetExecutableModule (new_executable_module_sp, false);
+ if (log)
+ {
+ ModuleSP exe_module_sp = m_target.GetExecutableModule ();
+ log->Printf ("Process::%s after looping through modules, target executable is %s",
+ __FUNCTION__,
+ exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>");
+ }
+ }
}
Error
@@ -3520,6 +3366,7 @@ Process::Halt (bool clear_thread_plans)
EventSP event_sp;
Error error (WillHalt());
+ bool restored_process_events = false;
if (error.Success())
{
@@ -3531,6 +3378,10 @@ Process::Halt (bool clear_thread_plans)
{
if (m_public_state.GetValue() == eStateAttaching)
{
+ // Don't hijack and eat the eStateExited as the code that was doing
+ // the attach will be waiting for this event...
+ RestorePrivateProcessEvents();
+ restored_process_events = true;
SetExitStatus(SIGKILL, "Cancelled async attach.");
Destroy ();
}
@@ -3547,7 +3398,7 @@ Process::Halt (bool clear_thread_plans)
// Wait for 1 second for the process to stop.
TimeValue timeout_time;
timeout_time = TimeValue::Now();
- timeout_time.OffsetWithSeconds(1);
+ timeout_time.OffsetWithSeconds(10);
bool got_event = halt_listener.WaitForEvent (&timeout_time, event_sp);
StateType state = ProcessEventData::GetStateFromEvent(event_sp.get());
@@ -3579,7 +3430,8 @@ Process::Halt (bool clear_thread_plans)
}
}
// Resume our private state thread before we post the event (if any)
- RestorePrivateProcessEvents();
+ if (!restored_process_events)
+ RestorePrivateProcessEvents();
// Post any event we might have consumed. If all goes well, we will have
// stopped the process, intercepted the event and set the interrupted
@@ -3671,6 +3523,9 @@ Process::Detach (bool keep_stopped)
}
}
+ m_thread_list.DiscardThreadPlans();
+ DisableAllBreakpointSites();
+
error = DoDetach(keep_stopped);
if (error.Success())
{
@@ -3738,9 +3593,14 @@ Process::Destroy ()
}
m_stdio_communication.StopReadThread();
m_stdio_communication.Disconnect();
+
if (m_process_input_reader)
+ {
+ m_process_input_reader->SetIsDone(true);
+ m_process_input_reader->Cancel();
m_process_input_reader.reset();
-
+ }
+
// If we exited when we were waiting for a process to stop, then
// forward the event here so we don't lose the event
if (exit_event_sp)
@@ -3831,7 +3691,7 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
break;
default:
// TODO: make this work correctly. For now always report
- // run if we aren't running so we don't miss any runnning
+ // run if we aren't running so we don't miss any running
// events. If I run the lldb/test/thread/a.out file and
// break at main.cpp:58, run and hit the breakpoints on
// multiple threads, then somehow during the stepping over
@@ -3866,32 +3726,33 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
{
if (log)
log->Printf ("Process::ShouldBroadcastEvent (%p) stopped due to an interrupt, state: %s",
- event_ptr,
+ static_cast<void*>(event_ptr),
StateAsCString(state));
+ // Even though we know we are going to stop, we should let the threads have a look at the stop,
+ // so they can properly set their state.
+ m_thread_list.ShouldStop (event_ptr);
return_value = true;
}
else
{
bool was_restarted = ProcessEventData::GetRestartedFromEvent (event_ptr);
bool should_resume = false;
-
+
// It makes no sense to ask "ShouldStop" if we've already been restarted...
// Asking the thread list is also not likely to go well, since we are running again.
// So in that case just report the event.
-
+
if (!was_restarted)
should_resume = m_thread_list.ShouldStop (event_ptr) == false;
-
+
if (was_restarted || should_resume || m_resume_requested)
{
Vote stop_vote = m_thread_list.ShouldReportStop (event_ptr);
if (log)
log->Printf ("Process::ShouldBroadcastEvent: should_stop: %i state: %s was_restarted: %i stop_vote: %d.",
- should_resume,
- StateAsCString(state),
- was_restarted,
- stop_vote);
-
+ should_resume, StateAsCString(state),
+ was_restarted, stop_vote);
+
switch (stop_vote)
{
case eVoteYes:
@@ -3902,15 +3763,17 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
return_value = false;
break;
}
-
+
if (!was_restarted)
{
if (log)
- log->Printf ("Process::ShouldBroadcastEvent (%p) Restarting process from state: %s", event_ptr, StateAsCString(state));
+ log->Printf ("Process::ShouldBroadcastEvent (%p) Restarting process from state: %s",
+ static_cast<void*>(event_ptr),
+ StateAsCString(state));
ProcessEventData::SetRestartedInEvent(event_ptr, true);
PrivateResume ();
}
-
+
}
else
{
@@ -3921,7 +3784,7 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
}
break;
}
-
+
// Forcing the next event delivery is a one shot deal. So reset it here.
m_force_next_event_delivery = false;
@@ -3931,14 +3794,13 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
// because the PublicState reflects the last event pulled off the queue, and there may be several
// events stacked up on the queue unserviced. So the PublicState may not reflect the last broadcasted event
// yet. m_last_broadcast_state gets updated here.
-
+
if (return_value)
m_last_broadcast_state = state;
-
+
if (log)
log->Printf ("Process::ShouldBroadcastEvent (%p) => new state: %s, last broadcast state: %s - %s",
- event_ptr,
- StateAsCString(state),
+ static_cast<void*>(event_ptr), StateAsCString(state),
StateAsCString(m_last_broadcast_state),
return_value ? "YES" : "NO");
return return_value;
@@ -3960,11 +3822,23 @@ Process::StartPrivateStateThread (bool force)
// Create a thread that watches our internal state and controls which
// events make it to clients (into the DCProcess event queue).
char thread_name[1024];
- if (already_running)
- snprintf(thread_name, sizeof(thread_name), "<lldb.process.internal-state-override(pid=%" PRIu64 ")>", GetID());
+
+ if (Host::MAX_THREAD_NAME_LENGTH <= 16)
+ {
+ // 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
- snprintf(thread_name, sizeof(thread_name), "<lldb.process.internal-state(pid=%" PRIu64 ")>", GetID());
-
+ {
+ if (already_running)
+ snprintf(thread_name, sizeof(thread_name), "<lldb.process.internal-state-override(pid=%" PRIu64 ")>", GetID());
+ else
+ snprintf(thread_name, sizeof(thread_name), "<lldb.process.internal-state(pid=%" PRIu64 ")>", 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);
@@ -4116,6 +3990,7 @@ Process::HandlePrivateEvent (EventSP &event_sp)
if (should_broadcast)
{
+ const bool is_hijacked = IsHijackedForEvent(eBroadcastBitStateChanged);
if (log)
{
log->Printf ("Process::%s (pid = %" PRIu64 ") broadcasting new state %s (old state %s) to %s",
@@ -4123,7 +3998,7 @@ Process::HandlePrivateEvent (EventSP &event_sp)
GetID(),
StateAsCString(new_state),
StateAsCString (GetState ()),
- IsHijackedForEvent(eBroadcastBitStateChanged) ? "hijacked" : "public");
+ is_hijacked ? "hijacked" : "public");
}
Process::ProcessEventData::SetUpdateStateOnRemoval(event_sp.get());
if (StateIsRunningState (new_state))
@@ -4132,9 +4007,46 @@ Process::HandlePrivateEvent (EventSP &event_sp)
// as this means the curses GUI is in use...
if (!GetTarget().GetDebugger().IsForwardingEvents())
PushProcessIOHandler ();
+ m_iohandler_sync.SetValue(true, eBroadcastAlways);
+ }
+ else if (StateIsStoppedState(new_state, false))
+ {
+ m_iohandler_sync.SetValue(false, eBroadcastNever);
+ if (!Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
+ {
+ // If the lldb_private::Debugger is handling the events, we don't
+ // want to pop the process IOHandler here, we want to do it when
+ // we receive the stopped event so we can carefully control when
+ // the process IOHandler is popped because when we stop we want to
+ // display some text stating how and why we stopped, then maybe some
+ // process/thread/frame info, and then we want the "(lldb) " prompt
+ // to show up. If we pop the process IOHandler here, then we will
+ // cause the command interpreter to become the top IOHandler after
+ // the process pops off and it will update its prompt right away...
+ // See the Debugger.cpp file where it calls the function as
+ // "process_sp->PopProcessIOHandler()" to see where I am talking about.
+ // Otherwise we end up getting overlapping "(lldb) " prompts and
+ // garbled output.
+ //
+ // If we aren't handling the events in the debugger (which is indicated
+ // by "m_target.GetDebugger().IsHandlingEvents()" returning false) or we
+ // are hijacked, then we always pop the process IO handler manually.
+ // Hijacking happens when the internal process state thread is running
+ // thread plans, or when commands want to run in synchronous mode
+ // and they call "process->WaitForProcessToStop()". An example of something
+ // that will hijack the events is a simple expression:
+ //
+ // (lldb) expr (int)puts("hello")
+ //
+ // This will cause the internal process state thread to resume and halt
+ // the process (and _it_ will hijack the eBroadcastBitStateChanged
+ // events) and we do need the IO handler to be pushed and popped
+ // correctly.
+
+ if (is_hijacked || m_target.GetDebugger().IsHandlingEvents() == false)
+ PopProcessIOHandler ();
+ }
}
- else if (!Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
- PopProcessIOHandler ();
BroadcastEvent (event_sp);
}
@@ -4168,7 +4080,8 @@ Process::RunPrivateStateThread ()
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
- log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") thread starting...", __FUNCTION__, this, GetID());
+ log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") thread starting...",
+ __FUNCTION__, static_cast<void*>(this), GetID());
bool exit_now = false;
while (!exit_now)
@@ -4178,13 +4091,15 @@ Process::RunPrivateStateThread ()
if (event_sp->BroadcasterIs(&m_private_state_control_broadcaster))
{
if (log)
- log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") got a control event: %d", __FUNCTION__, this, GetID(), event_sp->GetType());
+ log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") got a control event: %d",
+ __FUNCTION__, static_cast<void*>(this), GetID(),
+ event_sp->GetType());
switch (event_sp->GetType())
{
case eBroadcastInternalStateControlStop:
exit_now = true;
- break; // doing any internal state managment below
+ break; // doing any internal state management below
case eBroadcastInternalStateControlPause:
control_only = true;
@@ -4194,7 +4109,7 @@ Process::RunPrivateStateThread ()
control_only = false;
break;
}
-
+
m_private_state_control_wait.SetValue (true, eBroadcastAlways);
continue;
}
@@ -4203,13 +4118,17 @@ Process::RunPrivateStateThread ()
if (m_public_state.GetValue() == eStateAttaching)
{
if (log)
- log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") woke up with an interrupt while attaching - forwarding interrupt.", __FUNCTION__, this, GetID());
+ log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") woke up with an interrupt while attaching - forwarding interrupt.",
+ __FUNCTION__, static_cast<void*>(this),
+ GetID());
BroadcastEvent (eBroadcastBitInterrupt, NULL);
}
else
{
if (log)
- log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") woke up with an interrupt - Halting.", __FUNCTION__, this, GetID());
+ log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") woke up with an interrupt - Halting.",
+ __FUNCTION__, static_cast<void*>(this),
+ GetID());
Halt();
}
continue;
@@ -4233,7 +4152,9 @@ Process::RunPrivateStateThread ()
internal_state == eStateDetached )
{
if (log)
- log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") about to exit with internal state %s...", __FUNCTION__, this, GetID(), StateAsCString(internal_state));
+ log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") about to exit with internal state %s...",
+ __FUNCTION__, static_cast<void*>(this), GetID(),
+ StateAsCString(internal_state));
break;
}
@@ -4241,7 +4162,8 @@ Process::RunPrivateStateThread ()
// Verify log is still enabled before attempting to write to it...
if (log)
- log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") thread exiting...", __FUNCTION__, this, GetID());
+ log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") thread exiting...",
+ __FUNCTION__, static_cast<void*>(this), GetID());
m_public_run_lock.SetStopped();
m_private_state_control_wait.SetValue (true, eBroadcastAlways);
@@ -4303,8 +4225,14 @@ Process::ProcessEventData::DoOnRemoval (Event *event_ptr)
return;
m_process_sp->SetPublicState (m_state, Process::ProcessEventData::GetRestartedFromEvent(event_ptr));
-
- // If we're stopped and haven't restarted, then do the breakpoint commands here:
+
+ // If this is a halt event, even if the halt stopped with some reason other than a plain interrupt (e.g. we had
+ // already stopped for a breakpoint when the halt request came through) don't do the StopInfo actions, as they may
+ // end up restarting the process.
+ if (m_interrupted)
+ return;
+
+ // If we're stopped and haven't restarted, then do the StopInfo actions here:
if (m_state == eStateStopped && ! m_restarted)
{
ThreadList &curr_thread_list = m_process_sp->GetThreadList();
@@ -4418,7 +4346,8 @@ void
Process::ProcessEventData::Dump (Stream *s) const
{
if (m_process_sp)
- s->Printf(" process = %p (pid = %" PRIu64 "), ", m_process_sp.get(), m_process_sp->GetID());
+ s->Printf(" process = %p (pid = %" PRIu64 "), ",
+ static_cast<void*>(m_process_sp.get()), m_process_sp->GetID());
s->Printf("state = %s", StateAsCString(GetState()));
}
@@ -4601,7 +4530,9 @@ Process::GetAsyncProfileData (char *buf, size_t buf_size, Error &error)
{
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
- log->Printf ("Process::GetProfileData (buf = %p, size = %" PRIu64 ")", buf, (uint64_t)buf_size);
+ log->Printf ("Process::GetProfileData (buf = %p, size = %" PRIu64 ")",
+ static_cast<void*>(buf),
+ static_cast<uint64_t>(buf_size));
if (bytes_available > buf_size)
{
memcpy(buf, one_profile_data.c_str(), buf_size);
@@ -4631,7 +4562,9 @@ Process::GetSTDOUT (char *buf, size_t buf_size, Error &error)
{
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
- log->Printf ("Process::GetSTDOUT (buf = %p, size = %" PRIu64 ")", buf, (uint64_t)buf_size);
+ log->Printf ("Process::GetSTDOUT (buf = %p, size = %" PRIu64 ")",
+ static_cast<void*>(buf),
+ static_cast<uint64_t>(buf_size));
if (bytes_available > buf_size)
{
memcpy(buf, m_stdout_data.c_str(), buf_size);
@@ -4657,7 +4590,9 @@ Process::GetSTDERR (char *buf, size_t buf_size, Error &error)
{
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
- log->Printf ("Process::GetSTDERR (buf = %p, size = %" PRIu64 ")", buf, (uint64_t)buf_size);
+ log->Printf ("Process::GetSTDERR (buf = %p, size = %" PRIu64 ")",
+ static_cast<void*>(buf),
+ static_cast<uint64_t>(buf_size));
if (bytes_available > buf_size)
{
memcpy(buf, m_stderr_data.c_str(), buf_size);
@@ -4680,13 +4615,6 @@ Process::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_
process->AppendSTDOUT (static_cast<const char *>(src), src_len);
}
-void
-Process::ResetProcessIOHandler ()
-{
- m_process_input_reader.reset();
-}
-
-
class IOHandlerProcessSTDIO :
public IOHandler
{
@@ -4697,8 +4625,7 @@ public:
m_process (process),
m_read_file (),
m_write_file (write_fd, false),
- m_pipe_read(),
- m_pipe_write()
+ m_pipe ()
{
m_read_file.SetDescriptor(GetInputFD(), false);
}
@@ -4712,30 +4639,15 @@ public:
bool
OpenPipes ()
{
- if (m_pipe_read.IsValid() && m_pipe_write.IsValid())
+ if (m_pipe.IsValid())
return true;
-
- int fds[2];
-#ifdef _MSC_VER
- // pipe is not supported on windows so default to a fail condition
- int err = 1;
-#else
- int err = pipe(fds);
-#endif
- if (err == 0)
- {
- m_pipe_read.SetDescriptor(fds[0], true);
- m_pipe_write.SetDescriptor(fds[1], true);
- return true;
- }
- return false;
+ return m_pipe.Open();
}
void
ClosePipes()
{
- m_pipe_read.Close();
- m_pipe_write.Close();
+ m_pipe.Close();
}
// Each IOHandler gets to run until it is done. It should read data
@@ -4750,14 +4662,14 @@ public:
if (OpenPipes())
{
const int read_fd = m_read_file.GetDescriptor();
- const int pipe_read_fd = m_pipe_read.GetDescriptor();
+ const int pipe_read_fd = m_pipe.GetReadFileDescriptor();
TerminalState terminal_state;
terminal_state.Save (read_fd, false);
Terminal terminal(read_fd);
terminal.SetCanonical(false);
terminal.SetEcho(false);
// FD_ZERO, FD_SET are not supported on windows
-#ifndef _MSC_VER
+#ifndef _WIN32
while (!GetIsDone())
{
fd_set read_fdset;
@@ -4791,9 +4703,19 @@ public:
if (FD_ISSET (pipe_read_fd, &read_fdset))
{
// Consume the interrupt byte
- n = 1;
- m_pipe_read.Read (&ch, n);
- SetIsDone(true);
+ if (m_pipe.Read (&ch, 1) == 1)
+ {
+ switch (ch)
+ {
+ case 'q':
+ SetIsDone(true);
+ break;
+ case 'i':
+ if (StateIsRunningState(m_process->GetState()))
+ m_process->Halt();
+ break;
+ }
+ }
}
}
}
@@ -4828,16 +4750,40 @@ public:
virtual void
Cancel ()
{
- size_t n = 1;
- char ch = 'q';
- m_pipe_write.Write (&ch, n);
+ char ch = 'q'; // Send 'q' for quit
+ m_pipe.Write (&ch, 1);
}
- virtual void
+ virtual bool
Interrupt ()
{
- if (StateIsRunningState(m_process->GetState()))
- m_process->SendAsyncInterrupt();
+ // Do only things that are safe to do in an interrupt context (like in
+ // a SIGINT handler), like write 1 byte to a file descriptor. This will
+ // interrupt the IOHandlerProcessSTDIO::Run() and we can look at the byte
+ // that was written to the pipe and then call m_process->Halt() from a
+ // much safer location in code.
+ if (m_active)
+ {
+ char ch = 'i'; // Send 'i' for interrupt
+ return m_pipe.Write (&ch, 1) == 1;
+ }
+ else
+ {
+ // This IOHandler might be pushed on the stack, but not being run currently
+ // so do the right thing if we aren't actively watching for STDIN by sending
+ // the interrupt to the process. Otherwise the write to the pipe above would
+ // do nothing. This can happen when the command interpreter is running and
+ // gets a "expression ...". It will be on the IOHandler thread and sending
+ // the input is complete to the delegate which will cause the expression to
+ // run, which will push the process IO handler, but not run it.
+
+ if (StateIsRunningState(m_process->GetState()))
+ {
+ m_process->SendAsyncInterrupt();
+ return true;
+ }
+ }
+ return false;
}
virtual void
@@ -4850,28 +4796,10 @@ protected:
Process *m_process;
File m_read_file; // Read from this file (usually actual STDIN for LLDB
File m_write_file; // Write to this file (usually the master pty for getting io to debuggee)
- File m_pipe_read;
- File m_pipe_write;
-
+ Pipe m_pipe;
};
void
-Process::WatchForSTDIN (IOHandler &io_handler)
-{
-}
-
-void
-Process::CancelWatchForSTDIN (bool exited)
-{
- if (m_process_input_reader)
- {
- if (exited)
- m_process_input_reader->SetIsDone(true);
- m_process_input_reader->Cancel();
- }
-}
-
-void
Process::SetSTDIOFileDescriptor (int fd)
{
// First set up the Read Thread for reading/handling process I/O
@@ -4894,7 +4822,15 @@ Process::SetSTDIOFileDescriptor (int fd)
}
}
-void
+bool
+Process::ProcessIOHandlerIsActive ()
+{
+ IOHandlerSP io_handler_sp (m_process_input_reader);
+ if (io_handler_sp)
+ return m_target.GetDebugger().IsTopIOHandler (io_handler_sp);
+ return false;
+}
+bool
Process::PushProcessIOHandler ()
{
IOHandlerSP io_handler_sp (m_process_input_reader);
@@ -4902,18 +4838,18 @@ Process::PushProcessIOHandler ()
{
io_handler_sp->SetIsDone(false);
m_target.GetDebugger().PushIOHandler (io_handler_sp);
+ return true;
}
+ return false;
}
-void
+bool
Process::PopProcessIOHandler ()
{
IOHandlerSP io_handler_sp (m_process_input_reader);
if (io_handler_sp)
- {
- io_handler_sp->Cancel();
- m_target.GetDebugger().PopIOHandler (io_handler_sp);
- }
+ return m_target.GetDebugger().PopIOHandler (io_handler_sp);
+ return false;
}
// The process needs to know about installed plug-ins
@@ -4929,52 +4865,52 @@ Process::SettingsTerminate ()
Thread::SettingsTerminate ();
}
-ExecutionResults
+ExpressionResults
Process::RunThreadPlan (ExecutionContext &exe_ctx,
lldb::ThreadPlanSP &thread_plan_sp,
const EvaluateExpressionOptions &options,
Stream &errors)
{
- ExecutionResults return_value = eExecutionSetupError;
-
+ ExpressionResults return_value = eExpressionSetupError;
+
if (thread_plan_sp.get() == NULL)
{
errors.Printf("RunThreadPlan called with empty thread plan.");
- return eExecutionSetupError;
+ return eExpressionSetupError;
}
-
+
if (!thread_plan_sp->ValidatePlan(NULL))
{
errors.Printf ("RunThreadPlan called with an invalid thread plan.");
- return eExecutionSetupError;
+ return eExpressionSetupError;
}
-
+
if (exe_ctx.GetProcessPtr() != this)
{
errors.Printf("RunThreadPlan called on wrong process.");
- return eExecutionSetupError;
+ return eExpressionSetupError;
}
Thread *thread = exe_ctx.GetThreadPtr();
if (thread == NULL)
{
errors.Printf("RunThreadPlan called with invalid thread.");
- return eExecutionSetupError;
+ return eExpressionSetupError;
}
-
+
// We rely on the thread plan we are running returning "PlanCompleted" if when it successfully completes.
// For that to be true the plan can't be private - since private plans suppress themselves in the
// GetCompletedPlan call.
-
+
bool orig_plan_private = thread_plan_sp->GetPrivate();
thread_plan_sp->SetPrivate(false);
-
+
if (m_private_state.GetValue() != eStateStopped)
{
errors.Printf ("RunThreadPlan called while the private state was not stopped.");
- return eExecutionSetupError;
+ return eExpressionSetupError;
}
-
+
// Save the thread & frame from the exe_ctx for restoration after we run
const uint32_t thread_idx_id = thread->GetIndexID();
StackFrameSP selected_frame_sp = thread->GetSelectedFrame();
@@ -4985,17 +4921,17 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (!selected_frame_sp)
{
errors.Printf("RunThreadPlan called without a selected frame on thread %d", thread_idx_id);
- return eExecutionSetupError;
+ return eExpressionSetupError;
}
}
-
+
StackID ctx_frame_id = selected_frame_sp->GetStackID();
// N.B. Running the target may unset the currently selected thread and frame. We don't want to do that either,
// so we should arrange to reset them as well.
-
+
lldb::ThreadSP selected_thread_sp = GetThreadList().GetSelectedThread();
-
+
uint32_t selected_tid;
StackID selected_stack_id;
if (selected_thread_sp)
@@ -5021,7 +4957,6 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// we are fielding public events here.
if (log)
log->Printf ("Running thread plan on private state thread, spinning up another state thread to handle the events.");
-
backup_private_state_thread = m_private_state_thread;
@@ -5036,13 +4971,13 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// Have to make sure our public state is stopped, since otherwise the reporting logic below doesn't work correctly.
old_state = m_public_state.GetValue();
m_public_state.SetValueNoLock(eStateStopped);
-
+
// Now spin up the private state thread:
StartPrivateStateThread(true);
}
-
+
thread->QueueThreadPlan(thread_plan_sp, false); // This used to pass "true" does that make sense?
-
+
if (options.GetDebug())
{
// In this case, we aren't actually going to run, we just want to stop right away.
@@ -5051,22 +4986,22 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// is only cosmetic, and this functionality is only of use to lldb developers who can
// live with not pretty...
thread->Flush();
- return eExecutionStoppedForDebug;
+ return eExpressionStoppedForDebug;
}
-
+
Listener listener("lldb.process.listener.run-thread-plan");
-
+
lldb::EventSP event_to_broadcast_sp;
-
+
{
// This process event hijacker Hijacks the Public events and its destructor makes sure that the process events get
// restored on exit to the function.
//
// If the event needs to propagate beyond the hijacker (e.g., the process exits during execution), then the event
// is put into event_to_broadcast_sp for rebroadcasting.
-
+
ProcessEventHijacker run_thread_plan_hijacker (*this, &listener);
-
+
if (log)
{
StreamString s;
@@ -5076,66 +5011,114 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
thread->GetID(),
s.GetData());
}
-
+
bool got_event;
lldb::EventSP event_sp;
lldb::StateType stop_state = lldb::eStateInvalid;
-
+
TimeValue* timeout_ptr = NULL;
TimeValue real_timeout;
-
+
bool before_first_timeout = true; // This is set to false the first time that we have to halt the target.
bool do_resume = true;
bool handle_running_event = true;
const uint64_t default_one_thread_timeout_usec = 250000;
-
+
// This is just for accounting:
uint32_t num_resumes = 0;
+
+ uint32_t timeout_usec = options.GetTimeoutUsec();
+ uint32_t one_thread_timeout_usec;
+ uint32_t all_threads_timeout_usec = 0;
- TimeValue one_thread_timeout = TimeValue::Now();
- TimeValue final_timeout = one_thread_timeout;
+ // If we are going to run all threads the whole time, or if we are only going to run one thread,
+ // then we don't need the first timeout. So we set the final timeout, and pretend we are after the
+ // first timeout already.
- uint32_t timeout_usec = options.GetTimeoutUsec();
- if (options.GetTryAllThreads())
+ if (!options.GetStopOthers() || !options.GetTryAllThreads())
{
- // If we are running all threads then we take half the time to run all threads, bounded by
- // .25 sec.
- if (options.GetTimeoutUsec() == 0)
- one_thread_timeout.OffsetWithMicroSeconds(default_one_thread_timeout_usec);
- else
- {
- uint64_t computed_timeout = timeout_usec / 2;
- if (computed_timeout > default_one_thread_timeout_usec)
- computed_timeout = default_one_thread_timeout_usec;
- one_thread_timeout.OffsetWithMicroSeconds(computed_timeout);
- }
- final_timeout.OffsetWithMicroSeconds (timeout_usec);
+ before_first_timeout = false;
+ one_thread_timeout_usec = 0;
+ all_threads_timeout_usec = timeout_usec;
}
else
{
- if (timeout_usec != 0)
- final_timeout.OffsetWithMicroSeconds(timeout_usec);
+ uint32_t option_one_thread_timeout = options.GetOneThreadTimeoutUsec();
+
+ // If the overall wait is forever, then we only need to set the one thread timeout:
+ if (timeout_usec == 0)
+ {
+ if (option_one_thread_timeout != 0)
+ one_thread_timeout_usec = option_one_thread_timeout;
+ else
+ one_thread_timeout_usec = default_one_thread_timeout_usec;
+ }
+ else
+ {
+ // Otherwise, if the one thread timeout is set, make sure it isn't longer than the overall timeout,
+ // and use it, otherwise use half the total timeout, bounded by the default_one_thread_timeout_usec.
+ uint64_t computed_one_thread_timeout;
+ if (option_one_thread_timeout != 0)
+ {
+ if (timeout_usec < option_one_thread_timeout)
+ {
+ errors.Printf("RunThreadPlan called without one thread timeout greater than total timeout");
+ return eExpressionSetupError;
+ }
+ computed_one_thread_timeout = option_one_thread_timeout;
+ }
+ else
+ {
+ computed_one_thread_timeout = timeout_usec / 2;
+ if (computed_one_thread_timeout > default_one_thread_timeout_usec)
+ computed_one_thread_timeout = default_one_thread_timeout_usec;
+ }
+ one_thread_timeout_usec = computed_one_thread_timeout;
+ all_threads_timeout_usec = timeout_usec - one_thread_timeout_usec;
+
+ }
}
+
+ if (log)
+ log->Printf ("Stop others: %u, try all: %u, before_first: %u, one thread: %" PRIu32 " - all threads: %" PRIu32 ".\n",
+ options.GetStopOthers(),
+ options.GetTryAllThreads(),
+ before_first_timeout,
+ one_thread_timeout_usec,
+ all_threads_timeout_usec);
// This isn't going to work if there are unfetched events on the queue.
// Are there cases where we might want to run the remaining events here, and then try to
// call the function? That's probably being too tricky for our own good.
-
+
Event *other_events = listener.PeekAtNextEvent();
if (other_events != NULL)
{
errors.Printf("Calling RunThreadPlan with pending events on the queue.");
- return eExecutionSetupError;
+ return eExpressionSetupError;
}
-
+
// We also need to make sure that the next event is delivered. We might be calling a function as part of
// a thread plan, in which case the last delivered event could be the running event, and we don't want
// event coalescing to cause us to lose OUR running event...
ForceNextEventDelivery();
-
+
// This while loop must exit out the bottom, there's cleanup that we need to do when we are done.
// So don't call return anywhere within it.
+#ifdef LLDB_RUN_THREAD_HALT_WITH_EVENT
+ // It's pretty much impossible to write test cases for things like:
+ // One thread timeout expires, I go to halt, but the process already stopped
+ // on the function call stop breakpoint. Turning on this define will make us not
+ // fetch the first event till after the halt. So if you run a quick function, it will have
+ // completed, and the completion event will be waiting, when you interrupt for halt.
+ // The expression evaluation should still succeed.
+ bool miss_first_event = true;
+#endif
+ TimeValue one_thread_timeout;
+ TimeValue final_timeout;
+
+
while (1)
{
// We usually want to resume the process if we get to the top of the loop.
@@ -5146,11 +5129,11 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
do_resume,
handle_running_event,
before_first_timeout);
-
+
if (do_resume || handle_running_event)
{
// Do the initial resume and wait for the running event before going further.
-
+
if (do_resume)
{
num_resumes++;
@@ -5160,14 +5143,14 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
errors.Printf("Error resuming inferior the %d time: \"%s\".\n",
num_resumes,
resume_error.AsCString());
- return_value = eExecutionSetupError;
+ return_value = eExpressionSetupError;
break;
}
}
-
+
TimeValue resume_timeout = TimeValue::Now();
resume_timeout.OffsetWithMicroSeconds(500000);
-
+
got_event = listener.WaitForEvent(&resume_timeout, event_sp);
if (!got_event)
{
@@ -5176,16 +5159,16 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
num_resumes);
errors.Printf("Didn't get any event after resume %d, exiting.", num_resumes);
- return_value = eExecutionSetupError;
+ return_value = eExpressionSetupError;
break;
}
-
+
stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
if (stop_state != eStateRunning)
{
bool restarted = false;
-
+
if (stop_state == eStateStopped)
{
restarted = Process::ProcessEventData::GetRestartedFromEvent(event_sp.get());
@@ -5198,20 +5181,20 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
do_resume,
handle_running_event);
}
-
+
if (restarted)
{
// This is probably an overabundance of caution, I don't think I should ever get a stopped & restarted
// event here. But if I do, the best thing is to Halt and then get out of here.
Halt();
}
-
+
errors.Printf("Didn't get running event after initial resume, got %s instead.",
StateAsCString(stop_state));
- return_value = eExecutionSetupError;
+ return_value = eExpressionSetupError;
break;
}
-
+
if (log)
log->PutCString ("Process::RunThreadPlan(): resuming succeeded.");
// We need to call the function synchronously, so spin waiting for it to return.
@@ -5225,17 +5208,25 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (log)
log->PutCString ("Process::RunThreadPlan(): waiting for next event.");
}
-
+
if (before_first_timeout)
{
if (options.GetTryAllThreads())
+ {
+ one_thread_timeout = TimeValue::Now();
+ one_thread_timeout.OffsetWithMicroSeconds(one_thread_timeout_usec);
timeout_ptr = &one_thread_timeout;
+ }
else
{
if (timeout_usec == 0)
timeout_ptr = NULL;
else
+ {
+ final_timeout = TimeValue::Now();
+ final_timeout.OffsetWithMicroSeconds (timeout_usec);
timeout_ptr = &final_timeout;
+ }
}
}
else
@@ -5243,12 +5234,16 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (timeout_usec == 0)
timeout_ptr = NULL;
else
+ {
+ final_timeout = TimeValue::Now();
+ final_timeout.OffsetWithMicroSeconds (all_threads_timeout_usec);
timeout_ptr = &final_timeout;
+ }
}
-
+
do_resume = true;
handle_running_event = true;
-
+
// Now wait for the process to stop again:
event_sp.reset();
@@ -5266,8 +5261,18 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
}
}
+#ifdef LLDB_RUN_THREAD_HALT_WITH_EVENT
+ // See comment above...
+ if (miss_first_event)
+ {
+ usleep(1000);
+ miss_first_event = false;
+ got_event = false;
+ }
+ else
+#endif
got_event = listener.WaitForEvent (timeout_ptr, event_sp);
-
+
if (got_event)
{
if (event_sp.get())
@@ -5276,7 +5281,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (event_sp->GetType() == eBroadcastBitInterrupt)
{
Halt();
- return_value = eExecutionInterrupted;
+ return_value = eExpressionInterrupted;
errors.Printf ("Execution halted by user interrupt.");
if (log)
log->Printf ("Process::RunThreadPlan(): Got interrupted by eBroadcastBitInterrupted, exiting.");
@@ -5287,7 +5292,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
if (log)
log->Printf("Process::RunThreadPlan(): in while loop, got event: %s.", StateAsCString(stop_state));
-
+
switch (stop_state)
{
case lldb::eStateStopped:
@@ -5299,7 +5304,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// Ooh, our thread has vanished. Unlikely that this was successful execution...
if (log)
log->Printf ("Process::RunThreadPlan(): execution completed but our thread (index-id=%u) has vanished.", thread_idx_id);
- return_value = eExecutionInterrupted;
+ return_value = eExpressionInterrupted;
}
else
{
@@ -5313,17 +5318,15 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
keep_going = true;
do_resume = false;
handle_running_event = true;
-
+
}
else
{
-
StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
StopReason stop_reason = eStopReasonInvalid;
if (stop_info_sp)
stop_reason = stop_info_sp->GetStopReason();
-
-
+
// FIXME: We only check if the stop reason is plan complete, should we make sure that
// it is OUR plan that is complete?
if (stop_reason == eStopReasonPlanComplete)
@@ -5334,7 +5337,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// after this point.
if (thread_plan_sp)
thread_plan_sp->SetPrivate (orig_plan_private);
- return_value = eExecutionCompleted;
+ return_value = eExpressionCompleted;
}
else
{
@@ -5343,7 +5346,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
if (log)
log->Printf ("Process::RunThreadPlan() stopped for breakpoint: %s.", stop_info_sp->GetDescription());
- return_value = eExecutionHitBreakpoint;
+ return_value = eExpressionHitBreakpoint;
if (!options.DoesIgnoreBreakpoints())
{
event_to_broadcast_sp = event_sp;
@@ -5355,7 +5358,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
if (!options.DoesUnwindOnError())
event_to_broadcast_sp = event_sp;
- return_value = eExecutionInterrupted;
+ return_value = eExpressionInterrupted;
}
}
}
@@ -5374,16 +5377,16 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
default:
if (log)
log->Printf("Process::RunThreadPlan(): execution stopped with unexpected state: %s.", StateAsCString(stop_state));
-
+
if (stop_state == eStateExited)
event_to_broadcast_sp = event_sp;
-
+
errors.Printf ("Execution stopped with unexpected state.\n");
- return_value = eExecutionInterrupted;
+ return_value = eExpressionInterrupted;
break;
}
}
-
+
if (keep_going)
continue;
else
@@ -5393,7 +5396,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
if (log)
log->PutCString ("Process::RunThreadPlan(): got_event was true, but the event pointer was null. How odd...");
- return_value = eExecutionInterrupted;
+ return_value = eExpressionInterrupted;
break;
}
}
@@ -5402,15 +5405,24 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// If we didn't get an event that means we've timed out...
// We will interrupt the process here. Depending on what we were asked to do we will
// either exit, or try with all threads running for the same timeout.
-
+
if (log) {
if (options.GetTryAllThreads())
{
- uint64_t remaining_time = final_timeout - TimeValue::Now();
if (before_first_timeout)
- log->Printf ("Process::RunThreadPlan(): Running function with one thread timeout timed out, "
- "running till for %" PRIu64 " usec with all threads enabled.",
- remaining_time);
+ {
+ if (timeout_usec != 0)
+ {
+ log->Printf ("Process::RunThreadPlan(): Running function with one thread timeout timed out, "
+ "running for %" PRIu32 " usec with all threads enabled.",
+ all_threads_timeout_usec);
+ }
+ else
+ {
+ log->Printf ("Process::RunThreadPlan(): Running function with one thread timeout timed out, "
+ "running forever with all threads enabled.");
+ }
+ }
else
log->Printf ("Process::RunThreadPlan(): Restarting function with all threads enabled "
"and timeout: %u timed out, abandoning execution.",
@@ -5421,13 +5433,13 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
"abandoning execution.",
timeout_usec);
}
-
+
// It is possible that between the time we issued the Halt, and we get around to calling Halt the target
// could have stopped. That's fine, Halt will figure that out and send the appropriate Stopped event.
// BUT it is also possible that we stopped & restarted (e.g. hit a signal with "stop" set to false.) In
// that case, we'll get the stopped & restarted event, and we should go back to waiting for the Halt's
// stopped event. That's what this while loop does.
-
+
bool back_to_top = true;
uint32_t try_halt_again = 0;
bool do_halt = true;
@@ -5445,12 +5457,12 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
if (log)
log->PutCString ("Process::RunThreadPlan(): Halt succeeded.");
-
+
real_timeout = TimeValue::Now();
real_timeout.OffsetWithMicroSeconds(500000);
got_event = listener.WaitForEvent(&real_timeout, event_sp);
-
+
if (got_event)
{
stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
@@ -5461,22 +5473,22 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
&& Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get()))
log->PutCString (" Event was the Halt interruption event.");
}
-
+
if (stop_state == lldb::eStateStopped)
{
// Between the time we initiated the Halt and the time we delivered it, the process could have
// already finished its job. Check that here:
-
+
if (thread->IsThreadPlanDone (thread_plan_sp.get()))
{
if (log)
log->PutCString ("Process::RunThreadPlan(): Even though we timed out, the call plan was done. "
"Exiting wait loop.");
- return_value = eExecutionCompleted;
+ return_value = eExpressionCompleted;
back_to_top = false;
break;
}
-
+
if (Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
{
if (log)
@@ -5491,11 +5503,11 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
if (log)
log->PutCString ("Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting.");
- return_value = eExecutionInterrupted;
+ return_value = eExpressionInterrupted;
back_to_top = false;
break;
}
-
+
if (before_first_timeout)
{
// Set all the other threads to run, and return to the top of the loop, which will continue;
@@ -5512,7 +5524,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// Running all threads failed, so return Interrupted.
if (log)
log->PutCString("Process::RunThreadPlan(): running all threads timed out.");
- return_value = eExecutionInterrupted;
+ return_value = eExpressionInterrupted;
back_to_top = false;
break;
}
@@ -5522,7 +5534,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{ if (log)
log->PutCString("Process::RunThreadPlan(): halt said it succeeded, but I got no event. "
"I'm getting out of here passing Interrupted.");
- return_value = eExecutionInterrupted;
+ return_value = eExpressionInterrupted;
back_to_top = false;
break;
}
@@ -5533,14 +5545,14 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
continue;
}
}
-
+
if (!back_to_top || try_halt_again > num_retries)
break;
else
continue;
}
} // 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))
{
@@ -5554,23 +5566,23 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
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
// could happen:
// 1) The execution successfully completed
// 2) We hit a breakpoint, and ignore_breakpoints was true
// 3) We got some other error, and discard_on_error was true
- bool should_unwind = (return_value == eExecutionInterrupted && options.DoesUnwindOnError())
- || (return_value == eExecutionHitBreakpoint && options.DoesIgnoreBreakpoints());
-
- if (return_value == eExecutionCompleted
+ bool should_unwind = (return_value == eExpressionInterrupted && options.DoesUnwindOnError())
+ || (return_value == eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints());
+
+ if (return_value == eExpressionCompleted
|| should_unwind)
{
thread_plan_sp->RestoreThreadState();
}
-
+
// Now do some processing on the results of the run:
- if (return_value == eExecutionInterrupted || return_value == eExecutionHitBreakpoint)
+ if (return_value == eExpressionInterrupted || return_value == eExpressionHitBreakpoint)
{
if (log)
{
@@ -5585,7 +5597,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
StreamString ts;
const char *event_explanation = NULL;
-
+
do
{
if (!event_sp)
@@ -5607,7 +5619,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
event_explanation = "<no event data>";
break;
}
-
+
Process *process = event_data->GetProcessSP().get();
if (!process)
@@ -5615,34 +5627,34 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
event_explanation = "<no process>";
break;
}
-
+
ThreadList &thread_list = process->GetThreadList();
-
+
uint32_t num_threads = thread_list.GetSize();
uint32_t thread_index;
-
+
ts.Printf("<%u threads> ", num_threads);
-
+
for (thread_index = 0;
thread_index < num_threads;
++thread_index)
{
Thread *thread = thread_list.GetThreadAtIndex(thread_index).get();
-
+
if (!thread)
{
ts.Printf("<?> ");
continue;
}
-
+
ts.Printf("<0x%4.4" PRIx64 " ", thread->GetID());
RegisterContext *register_context = thread->GetRegisterContext().get();
-
+
if (register_context)
ts.Printf("[ip 0x%" PRIx64 "] ", register_context->GetPC());
else
ts.Printf("[ip unknown] ");
-
+
lldb::StopInfoSP stop_info_sp = thread->GetStopInfo();
if (stop_info_sp)
{
@@ -5652,35 +5664,37 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
}
ts.Printf(">");
}
-
+
event_explanation = ts.GetData();
}
} while (0);
-
+
if (event_explanation)
log->Printf("Process::RunThreadPlan(): execution interrupted: %s %s", s.GetData(), event_explanation);
else
log->Printf("Process::RunThreadPlan(): execution interrupted: %s", s.GetData());
}
-
+
if (should_unwind)
{
if (log)
- log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.", thread_plan_sp.get());
+ log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.",
+ static_cast<void*>(thread_plan_sp.get()));
thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
thread_plan_sp->SetPrivate (orig_plan_private);
}
else
{
if (log)
- log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - for plan: %p not discarding.", thread_plan_sp.get());
+ log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - for plan: %p not discarding.",
+ static_cast<void*>(thread_plan_sp.get()));
}
}
- else if (return_value == eExecutionSetupError)
+ else if (return_value == eExpressionSetupError)
{
if (log)
log->PutCString("Process::RunThreadPlan(): execution set up error.");
-
+
if (options.DoesUnwindOnError())
{
thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
@@ -5693,13 +5707,13 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
if (log)
log->PutCString("Process::RunThreadPlan(): thread plan is done");
- return_value = eExecutionCompleted;
+ return_value = eExpressionCompleted;
}
else if (thread->WasThreadPlanDiscarded (thread_plan_sp.get()))
{
if (log)
log->PutCString("Process::RunThreadPlan(): thread plan was discarded");
- return_value = eExecutionDiscarded;
+ return_value = eExpressionDiscarded;
}
else
{
@@ -5714,7 +5728,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
}
}
}
-
+
// Thread we ran the function in may have gone away because we ran the target
// Check that it's still there, and if it is put it back in the context. Also restore the
// frame in the context if it is still present.
@@ -5723,10 +5737,10 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
exe_ctx.SetFrameSP (thread->GetFrameWithStackID (ctx_frame_id));
}
-
+
// Also restore the current process'es selected frame & thread, since this function calling may
// be done behind the user's back.
-
+
if (selected_tid != LLDB_INVALID_THREAD_ID)
{
if (GetThreadList().SetSelectedThreadByIndexID (selected_tid) && selected_stack_id.IsValid())
@@ -5739,46 +5753,52 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
}
}
}
-
+
// If the process exited during the run of the thread plan, notify everyone.
-
+
if (event_to_broadcast_sp)
{
if (log)
log->PutCString("Process::RunThreadPlan(): rebroadcasting event.");
BroadcastEvent(event_to_broadcast_sp);
}
-
+
return return_value;
}
const char *
-Process::ExecutionResultAsCString (ExecutionResults result)
+Process::ExecutionResultAsCString (ExpressionResults result)
{
const char *result_name;
switch (result)
{
- case eExecutionCompleted:
- result_name = "eExecutionCompleted";
+ case eExpressionCompleted:
+ result_name = "eExpressionCompleted";
break;
- case eExecutionDiscarded:
- result_name = "eExecutionDiscarded";
+ case eExpressionDiscarded:
+ result_name = "eExpressionDiscarded";
break;
- case eExecutionInterrupted:
- result_name = "eExecutionInterrupted";
+ case eExpressionInterrupted:
+ result_name = "eExpressionInterrupted";
break;
- case eExecutionHitBreakpoint:
- result_name = "eExecutionHitBreakpoint";
+ case eExpressionHitBreakpoint:
+ result_name = "eExpressionHitBreakpoint";
break;
- case eExecutionSetupError:
- result_name = "eExecutionSetupError";
+ case eExpressionSetupError:
+ result_name = "eExpressionSetupError";
break;
- case eExecutionTimedOut:
- result_name = "eExecutionTimedOut";
+ case eExpressionParseError:
+ result_name = "eExpressionParseError";
break;
- case eExecutionStoppedForDebug:
- result_name = "eExecutionStoppedForDebug";
+ case eExpressionResultUnavailable:
+ result_name = "eExpressionResultUnavailable";
+ break;
+ case eExpressionTimedOut:
+ result_name = "eExpressionTimedOut";
+ break;
+ case eExpressionStoppedForDebug:
+ result_name = "eExpressionStoppedForDebug";
break;
}
return result_name;
@@ -5823,25 +5843,47 @@ Process::GetThreadStatus (Stream &strm,
{
size_t num_thread_infos_dumped = 0;
- Mutex::Locker locker (GetThreadList().GetMutex());
- const size_t num_threads = GetThreadList().GetSize();
+ // You can't hold the thread list lock while calling Thread::GetStatus. That very well might run code (e.g. if we need it
+ // to get return values or arguments.) For that to work the process has to be able to acquire it. So instead copy the thread
+ // ID's, and look them up one by one:
+
+ uint32_t num_threads;
+ std::vector<uint32_t> thread_index_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);
+ for (idx = 0; idx < num_threads; ++idx)
+ thread_index_array[idx] = curr_thread_list.GetThreadAtIndex(idx)->GetID();
+ }
+
for (uint32_t i = 0; i < num_threads; i++)
{
- Thread *thread = GetThreadList().GetThreadAtIndex(i).get();
- if (thread)
+ ThreadSP thread_sp(GetThreadList().FindThreadByID(thread_index_array[i]));
+ if (thread_sp)
{
if (only_threads_with_stop_reason)
{
- StopInfoSP stop_info_sp = thread->GetStopInfo();
+ StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
if (stop_info_sp.get() == NULL || !stop_info_sp->IsValid())
continue;
}
- thread->GetStatus (strm,
+ thread_sp->GetStatus (strm,
start_frame,
num_frames,
num_frames_with_source);
++num_thread_infos_dumped;
}
+ else
+ {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("Process::GetThreadStatus - thread 0x" PRIu64 " vanished while running Thread::GetStatus.");
+
+ }
}
return num_thread_infos_dumped;
}
@@ -5897,6 +5939,10 @@ Process::Flush ()
void
Process::DidExec ()
{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf ("Process::%s()", __FUNCTION__);
+
Target &target = GetTarget();
target.CleanupProcess ();
target.ClearModules(false);
@@ -5905,6 +5951,7 @@ Process::DidExec ()
m_system_runtime_ap.reset();
m_os_ap.reset();
m_dyld_ap.reset();
+ m_jit_loaders_ap.reset();
m_image_tokens.clear();
m_allocated_memory_cache.Clear();
m_language_runtimes.clear();
@@ -5955,3 +6002,14 @@ Process::ResolveIndirectFunction(const Address *address, Error &error)
return function_addr;
}
+void
+Process::ModulesDidLoad (ModuleList &module_list)
+{
+ SystemRuntime *sys_runtime = GetSystemRuntime();
+ if (sys_runtime)
+ {
+ sys_runtime->ModulesDidLoad (module_list);
+ }
+
+ GetJITLoaders().ModulesDidLoad (module_list);
+}
diff --git a/source/Target/ProcessInfo.cpp b/source/Target/ProcessInfo.cpp
new file mode 100644
index 000000000000..22da2c6a2a29
--- /dev/null
+++ b/source/Target/ProcessInfo.cpp
@@ -0,0 +1,138 @@
+//===-- ProcessInfo.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/ProcessInfo.h"
+
+// C Includes
+#include <limits.h>
+
+using namespace lldb;
+using namespace lldb_private;
+
+ProcessInfo::ProcessInfo () :
+ m_executable (),
+ m_arguments (),
+ m_environment (),
+ m_uid (UINT32_MAX),
+ m_gid (UINT32_MAX),
+ m_arch(),
+ m_pid (LLDB_INVALID_PROCESS_ID)
+{
+}
+
+ProcessInfo::ProcessInfo (const char *name, const ArchSpec &arch, lldb::pid_t pid) :
+ m_executable (name, false),
+ m_arguments (),
+ m_environment(),
+ m_uid (UINT32_MAX),
+ m_gid (UINT32_MAX),
+ m_arch (arch),
+ m_pid (pid)
+{
+}
+
+void
+ProcessInfo::Clear ()
+{
+ m_executable.Clear();
+ m_arguments.Clear();
+ m_environment.Clear();
+ m_uid = UINT32_MAX;
+ m_gid = UINT32_MAX;
+ m_arch.Clear();
+ m_pid = LLDB_INVALID_PROCESS_ID;
+}
+
+const char *
+ProcessInfo::GetName() const
+{
+ return m_executable.GetFilename().GetCString();
+}
+
+size_t
+ProcessInfo::GetNameLength() const
+{
+ return m_executable.GetFilename().GetLength();
+}
+
+void
+ProcessInfo::SetExecutableFile (const FileSpec &exe_file, bool add_exe_file_as_first_arg)
+{
+ if (exe_file)
+ {
+ m_executable = exe_file;
+ if (add_exe_file_as_first_arg)
+ {
+ char filename[PATH_MAX];
+ if (exe_file.GetPath(filename, sizeof(filename)))
+ m_arguments.InsertArgumentAtIndex (0, filename);
+ }
+ }
+ else
+ {
+ m_executable.Clear();
+ }
+}
+
+const char *
+ProcessInfo::GetArg0 () const
+{
+ if (m_arg0.empty())
+ return NULL;
+ return m_arg0.c_str();
+}
+
+void
+ProcessInfo::SetArg0 (const char *arg)
+{
+ if (arg && arg[0])
+ m_arg0 = arg;
+ else
+ m_arg0.clear();
+}
+
+void
+ProcessInfo::SetArguments (char const **argv, bool first_arg_is_executable)
+{
+ m_arguments.SetArguments (argv);
+
+ // Is the first argument the executable?
+ if (first_arg_is_executable)
+ {
+ const char *first_arg = m_arguments.GetArgumentAtIndex (0);
+ if (first_arg)
+ {
+ // Yes the first argument is an executable, set it as the executable
+ // in the launch options. Don't resolve the file path as the path
+ // could be a remote platform path
+ const bool resolve = false;
+ m_executable.SetFile(first_arg, resolve);
+ }
+ }
+}
+void
+ProcessInfo::SetArguments (const Args& args, bool first_arg_is_executable)
+{
+ // Copy all arguments
+ m_arguments = args;
+
+ // Is the first argument the executable?
+ if (first_arg_is_executable)
+ {
+ const char *first_arg = m_arguments.GetArgumentAtIndex (0);
+ if (first_arg)
+ {
+ // Yes the first argument is an executable, set it as the executable
+ // in the launch options. Don't resolve the file path as the path
+ // could be a remote platform path
+ const bool resolve = false;
+ m_executable.SetFile(first_arg, resolve);
+ }
+ }
+}
diff --git a/source/Target/ProcessLaunchInfo.cpp b/source/Target/ProcessLaunchInfo.cpp
new file mode 100644
index 000000000000..830f1470ed98
--- /dev/null
+++ b/source/Target/ProcessLaunchInfo.cpp
@@ -0,0 +1,459 @@
+//===-- ProcessLaunchInfo.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/Config.h"
+
+#ifndef LLDB_DISABLE_POSIX
+#include <spawn.h>
+#endif
+
+#include "lldb/Target/ProcessLaunchInfo.h"
+#include "lldb/Target/FileAction.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------------
+// ProcessLaunchInfo member functions
+//----------------------------------------------------------------------------
+
+ProcessLaunchInfo::ProcessLaunchInfo () :
+ ProcessInfo(),
+ m_working_dir (),
+ m_plugin_name (),
+ m_shell (),
+ m_flags (0),
+ 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 ()
+{
+}
+
+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()
+{
+ if (stdin_path)
+ {
+ FileAction file_action;
+ const bool read = true;
+ const bool write = false;
+ if (file_action.Open(STDIN_FILENO, stdin_path, read, write))
+ AppendFileAction (file_action);
+ }
+ if (stdout_path)
+ {
+ FileAction file_action;
+ const bool read = false;
+ const bool write = true;
+ if (file_action.Open(STDOUT_FILENO, stdout_path, read, write))
+ AppendFileAction (file_action);
+ }
+ if (stderr_path)
+ {
+ FileAction file_action;
+ const bool read = false;
+ const bool write = true;
+ if (file_action.Open(STDERR_FILENO, stderr_path, read, write))
+ AppendFileAction (file_action);
+ }
+ if (working_directory)
+ SetWorkingDirectory(working_directory);
+}
+
+bool
+ProcessLaunchInfo::AppendCloseFileAction (int fd)
+{
+ FileAction file_action;
+ if (file_action.Close (fd))
+ {
+ AppendFileAction (file_action);
+ return true;
+ }
+ return false;
+}
+
+bool
+ProcessLaunchInfo::AppendDuplicateFileAction (int fd, int dup_fd)
+{
+ FileAction file_action;
+ if (file_action.Duplicate (fd, dup_fd))
+ {
+ AppendFileAction (file_action);
+ return true;
+ }
+ return false;
+}
+
+bool
+ProcessLaunchInfo::AppendOpenFileAction (int fd, const char *path, bool read, bool write)
+{
+ FileAction file_action;
+ if (file_action.Open (fd, path, read, write))
+ {
+ AppendFileAction (file_action);
+ return true;
+ }
+ return false;
+}
+
+bool
+ProcessLaunchInfo::AppendSuppressFileAction (int fd, bool read, bool write)
+{
+ FileAction file_action;
+ if (file_action.Open (fd, "/dev/null", read, write))
+ {
+ AppendFileAction (file_action);
+ return true;
+ }
+ return false;
+}
+
+const FileAction *
+ProcessLaunchInfo::GetFileActionAtIndex(size_t idx) const
+{
+ if (idx < m_file_actions.size())
+ return &m_file_actions[idx];
+ return NULL;
+}
+
+const FileAction *
+ProcessLaunchInfo::GetFileActionForFD(int fd) const
+{
+ for (size_t idx=0, count=m_file_actions.size(); idx < count; ++idx)
+ {
+ if (m_file_actions[idx].GetFD () == fd)
+ return &m_file_actions[idx];
+ }
+ return NULL;
+}
+
+const char *
+ProcessLaunchInfo::GetWorkingDirectory () const
+{
+ if (m_working_dir.empty())
+ return NULL;
+ return m_working_dir.c_str();
+}
+
+void
+ProcessLaunchInfo::SetWorkingDirectory (const char *working_dir)
+{
+ if (working_dir && working_dir[0])
+ m_working_dir.assign (working_dir);
+ else
+ m_working_dir.clear();
+}
+
+const char *
+ProcessLaunchInfo::GetProcessPluginName () const
+{
+ if (m_plugin_name.empty())
+ return NULL;
+ return m_plugin_name.c_str();
+}
+
+void
+ProcessLaunchInfo::SetProcessPluginName (const char *plugin)
+{
+ if (plugin && plugin[0])
+ m_plugin_name.assign (plugin);
+ else
+ m_plugin_name.clear();
+}
+
+const char *
+ProcessLaunchInfo::GetShell () const
+{
+ if (m_shell.empty())
+ return NULL;
+ return m_shell.c_str();
+}
+
+void
+ProcessLaunchInfo::SetShell (const char * path)
+{
+ if (path && path[0])
+ {
+ m_shell.assign (path);
+ m_flags.Set (lldb::eLaunchFlagLaunchInShell);
+ }
+ else
+ {
+ m_shell.clear();
+ m_flags.Clear (lldb::eLaunchFlagLaunchInShell);
+ }
+}
+
+void
+ProcessLaunchInfo::SetLaunchInSeparateProcessGroup (bool separate)
+{
+ if (separate)
+ m_flags.Set(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
+ else
+ m_flags.Clear (lldb::eLaunchFlagLaunchInSeparateProcessGroup);
+
+}
+
+void
+ProcessLaunchInfo::Clear ()
+{
+ ProcessInfo::Clear();
+ m_working_dir.clear();
+ m_plugin_name.clear();
+ m_shell.clear();
+ m_flags.Clear();
+ m_file_actions.clear();
+ m_resume_count = 0;
+ m_hijack_listener_sp.reset();
+}
+
+void
+ProcessLaunchInfo::SetMonitorProcessCallback (Host::MonitorChildProcessCallback callback,
+ void *baton,
+ bool monitor_signals)
+{
+ m_monitor_callback = callback;
+ m_monitor_callback_baton = baton;
+ m_monitor_signals = monitor_signals;
+}
+
+bool
+ProcessLaunchInfo::MonitorProcess () const
+{
+ if (m_monitor_callback && ProcessIDIsValid())
+ {
+ Host::StartMonitoringChildProcess (m_monitor_callback,
+ m_monitor_callback_baton,
+ GetProcessID(),
+ m_monitor_signals);
+ return true;
+ }
+ return false;
+}
+
+void
+ProcessLaunchInfo::SetDetachOnError (bool enable)
+{
+ if (enable)
+ m_flags.Set(lldb::eLaunchFlagDetachOnError);
+ else
+ m_flags.Clear(lldb::eLaunchFlagDetachOnError);
+}
+
+void
+ProcessLaunchInfo::FinalizeFileActions (Target *target, bool default_to_use_pty)
+{
+ // 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 ||
+ GetFileActionForFD(STDERR_FILENO) == NULL)
+ {
+ if (m_flags.Test(eLaunchFlagDisableSTDIO))
+ {
+ AppendSuppressFileAction (STDIN_FILENO , true, false);
+ AppendSuppressFileAction (STDOUT_FILENO, false, true);
+ AppendSuppressFileAction (STDERR_FILENO, false, true);
+ }
+ else
+ {
+ // Check for any values that might have gotten set with any of:
+ // (lldb) settings set target.input-path
+ // (lldb) settings set target.output-path
+ // (lldb) settings set target.error-path
+ FileSpec in_path;
+ FileSpec out_path;
+ FileSpec err_path;
+ if (target)
+ {
+ in_path = target->GetStandardInputPath();
+ out_path = target->GetStandardOutputPath();
+ err_path = target->GetStandardErrorPath();
+ }
+
+ char path[PATH_MAX];
+ if (in_path && in_path.GetPath(path, sizeof(path)))
+ AppendOpenFileAction(STDIN_FILENO, path, true, false);
+
+ if (out_path && out_path.GetPath(path, sizeof(path)))
+ AppendOpenFileAction(STDOUT_FILENO, path, false, true);
+
+ if (err_path && err_path.GetPath(path, sizeof(path)))
+ AppendOpenFileAction(STDERR_FILENO, path, false, true);
+
+ 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 (!in_path) {
+ AppendOpenFileAction(STDIN_FILENO, slave_path, true, false);
+ }
+
+ if (!out_path) {
+ AppendOpenFileAction(STDOUT_FILENO, slave_path, false, true);
+ }
+
+ if (!err_path) {
+ AppendOpenFileAction(STDERR_FILENO, slave_path, false, true);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+bool
+ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error,
+ bool localhost,
+ bool will_debug,
+ bool first_arg_is_full_shell_command,
+ int32_t num_resumes)
+{
+ error.Clear();
+
+ if (GetFlags().Test (eLaunchFlagLaunchInShell))
+ {
+ const char *shell_executable = GetShell();
+ if (shell_executable)
+ {
+ 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;
+ }
+
+ 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");
+ StreamString shell_command;
+ if (will_debug)
+ {
+ // Add a modified PATH environment variable in case argv[0]
+ // is a relative path
+ const char *argv0 = argv[0];
+ if (argv0 && (argv0[0] != '/' && argv0[0] != '~'))
+ {
+ // 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")
+ const char *working_dir = GetWorkingDirectory();
+ // Be sure to put quotes around PATH's value in case any paths have spaces...
+ std::string new_path("PATH=\"");
+ const size_t empty_path_len = new_path.size();
+
+ if (working_dir && working_dir[0])
+ {
+ new_path += working_dir;
+ }
+ else
+ {
+ char current_working_dir[PATH_MAX];
+ const char *cwd = getcwd(current_working_dir, sizeof(current_working_dir));
+ if (cwd && cwd[0])
+ new_path += cwd;
+ }
+ const char *curr_path = getenv("PATH");
+ if (curr_path)
+ {
+ if (new_path.size() > empty_path_len)
+ new_path += ':';
+ new_path += curr_path;
+ }
+ new_path += "\" ";
+ shell_command.PutCString(new_path.c_str());
+ }
+
+ shell_command.PutCString ("exec");
+
+ // Only Apple supports /usr/bin/arch being able to specify the architecture
+ if (GetArchitecture().IsValid() && // Valid architecture
+ GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple && // Apple only
+ GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) // Don't do this for x86_64h
+ {
+ shell_command.Printf(" /usr/bin/arch -arch %s", GetArchitecture().GetArchitectureName());
+ // Set the resume count to 2:
+ // 1 - stop in shell
+ // 2 - stop in /usr/bin/arch
+ // 3 - then we will stop in our program
+ SetResumeCount(num_resumes + 1);
+ }
+ else
+ {
+ // Set the resume count to 1:
+ // 1 - stop in shell
+ // 2 - then we will stop in our program
+ SetResumeCount(num_resumes);
+ }
+ }
+
+ if (first_arg_is_full_shell_command)
+ {
+ // There should only be one argument that is the shell command itself to be used as is
+ if (argv[0] && !argv[1])
+ shell_command.Printf("%s", argv[0]);
+ else
+ return false;
+ }
+ else
+ {
+ for (size_t i=0; argv[i] != NULL; ++i)
+ {
+ const char *arg = Args::GetShellSafeArgument (argv[i], safe_arg);
+ shell_command.Printf(" %s", arg);
+ }
+ }
+ shell_arguments.AppendArgument (shell_command.GetString().c_str());
+ m_executable.SetFile(shell_executable, false);
+ m_arguments = shell_arguments;
+ return true;
+ }
+ else
+ {
+ error.SetErrorString ("invalid shell path");
+ }
+ }
+ else
+ {
+ error.SetErrorString ("not launching in shell");
+ }
+ return false;
+}
diff --git a/source/Target/Queue.cpp b/source/Target/Queue.cpp
index 2b9d2a0ed9a4..7cfa6fa5582f 100644
--- a/source/Target/Queue.cpp
+++ b/source/Target/Queue.cpp
@@ -23,7 +23,8 @@ Queue::Queue (ProcessSP process_sp, lldb::queue_id_t queue_id, const char *queue
m_running_work_items_count(0),
m_pending_work_items_count(0),
m_pending_items(),
- m_dispatch_queue_t_addr(LLDB_INVALID_ADDRESS)
+ m_dispatch_queue_t_addr(LLDB_INVALID_ADDRESS),
+ m_kind (eQueueKindUnknown)
{
if (queue_name)
m_queue_name = queue_name;
@@ -125,3 +126,15 @@ Queue::GetPendingItems ()
}
return m_pending_items;
}
+
+lldb::QueueKind
+Queue::GetKind ()
+{
+ return m_kind;
+}
+
+void
+Queue::SetKind (lldb::QueueKind kind)
+{
+ m_kind = kind;
+}
diff --git a/source/Target/QueueItem.cpp b/source/Target/QueueItem.cpp
index bb6762829ca6..002187b8d204 100644
--- a/source/Target/QueueItem.cpp
+++ b/source/Target/QueueItem.cpp
@@ -15,10 +15,13 @@
using namespace lldb;
using namespace lldb_private;
-QueueItem::QueueItem (QueueSP queue_sp) :
+QueueItem::QueueItem (QueueSP queue_sp, ProcessSP process_sp, lldb::addr_t item_ref, lldb_private::Address address) :
m_queue_wp (),
+ m_process_wp (),
+ m_item_ref (item_ref),
+ m_address (address),
+ m_have_fetched_entire_item (false),
m_kind (eQueueItemKindUnknown),
- m_address (),
m_item_that_enqueued_this_ref (LLDB_INVALID_ADDRESS),
m_enqueueing_thread_id (LLDB_INVALID_THREAD_ID),
m_enqueueing_queue_id (LLDB_INVALID_QUEUE_ID),
@@ -30,6 +33,7 @@ QueueItem::QueueItem (QueueSP queue_sp) :
m_target_queue_label()
{
m_queue_wp = queue_sp;
+ m_process_wp = process_sp;
}
QueueItem::~QueueItem ()
@@ -37,8 +41,9 @@ QueueItem::~QueueItem ()
}
QueueItemKind
-QueueItem::GetKind() const
+QueueItem::GetKind()
{
+ FetchEntireItem ();
return m_kind;
}
@@ -63,6 +68,7 @@ QueueItem::SetAddress (Address addr)
ThreadSP
QueueItem::GetExtendedBacktraceThread (ConstString type)
{
+ FetchEntireItem ();
ThreadSP return_thread;
QueueSP queue_sp = m_queue_wp.lock();
if (queue_sp)
@@ -75,3 +81,76 @@ QueueItem::GetExtendedBacktraceThread (ConstString type)
}
return return_thread;
}
+
+lldb::addr_t
+QueueItem::GetItemThatEnqueuedThis ()
+{
+ FetchEntireItem ();
+ return m_item_that_enqueued_this_ref;
+}
+
+lldb::tid_t
+QueueItem::GetEnqueueingThreadID ()
+{
+ FetchEntireItem ();
+ return m_enqueueing_thread_id;
+}
+
+lldb::queue_id_t
+QueueItem::GetEnqueueingQueueID ()
+{
+ FetchEntireItem ();
+ return m_enqueueing_queue_id;
+}
+
+uint32_t
+QueueItem::GetStopID ()
+{
+ FetchEntireItem ();
+ return m_stop_id;
+}
+
+std::vector<lldb::addr_t> &
+QueueItem::GetEnqueueingBacktrace ()
+{
+ FetchEntireItem ();
+ return m_backtrace;
+}
+
+std::string
+QueueItem::GetThreadLabel ()
+{
+ FetchEntireItem ();
+ return m_thread_label;
+}
+
+std::string
+QueueItem::GetQueueLabel ()
+{
+ FetchEntireItem ();
+ return m_queue_label;
+}
+
+
+ProcessSP
+QueueItem::GetProcessSP()
+{
+ return m_process_wp.lock ();
+}
+
+void
+QueueItem::FetchEntireItem()
+{
+ if (m_have_fetched_entire_item == true)
+ return;
+ ProcessSP process_sp = m_process_wp.lock();
+ if (process_sp)
+ {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime();
+ if (runtime)
+ {
+ runtime->CompleteQueueItem (this, m_item_ref);
+ m_have_fetched_entire_item = true;
+ }
+ }
+}
diff --git a/source/Target/RegisterContext.cpp b/source/Target/RegisterContext.cpp
index 93dce3ea0edc..97f6f21c53c8 100644
--- a/source/Target/RegisterContext.cpp
+++ b/source/Target/RegisterContext.cpp
@@ -82,7 +82,7 @@ RegisterContext::GetRegisterInfoByName (const char *reg_name, uint32_t start_idx
}
const RegisterInfo *
-RegisterContext::GetRegisterInfo (uint32_t kind, uint32_t num)
+RegisterContext::GetRegisterInfo (lldb::RegisterKind kind, uint32_t num)
{
const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num);
if (reg_num == LLDB_INVALID_REGNUM)
@@ -488,7 +488,7 @@ RegisterContext::CalculateExecutionContext (ExecutionContext &exe_ctx)
bool
-RegisterContext::ConvertBetweenRegisterKinds (int source_rk, uint32_t source_regnum, int target_rk, uint32_t& target_regnum)
+RegisterContext::ConvertBetweenRegisterKinds (lldb::RegisterKind source_rk, uint32_t source_regnum, lldb::RegisterKind target_rk, uint32_t& target_regnum)
{
const uint32_t num_registers = GetRegisterCount();
for (uint32_t reg = 0; reg < num_registers; ++reg)
diff --git a/source/Target/SectionLoadHistory.cpp b/source/Target/SectionLoadHistory.cpp
index 527168ce42af..1e5c4175a2bf 100644
--- a/source/Target/SectionLoadHistory.cpp
+++ b/source/Target/SectionLoadHistory.cpp
@@ -47,15 +47,7 @@ SectionLoadHistory::GetLastStopID() const
SectionLoadList *
SectionLoadHistory::GetSectionLoadListForStopID (uint32_t stop_id, bool read_only)
{
- if (m_stop_id_to_section_load_list.empty())
- {
- SectionLoadListSP section_load_list_sp(new SectionLoadList());
- if (stop_id == eStopIDNow)
- stop_id = 0;
- m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
- return section_load_list_sp.get();
- }
- else
+ if (!m_stop_id_to_section_load_list.empty())
{
if (read_only)
{
@@ -65,7 +57,7 @@ SectionLoadHistory::GetSectionLoadListForStopID (uint32_t stop_id, bool read_onl
if (stop_id == eStopIDNow)
{
// If we are asking for the latest and greatest value, it is always
- // at the end of our list becuase that will be the highest stop ID.
+ // at the end of our list because that will be the highest stop ID.
StopIDToSectionLoadList::reverse_iterator rpos = m_stop_id_to_section_load_list.rbegin();
return rpos->second.get();
}
@@ -105,13 +97,18 @@ SectionLoadHistory::GetSectionLoadListForStopID (uint32_t stop_id, bool read_onl
return section_load_list_sp.get();
}
}
- return NULL;
+ SectionLoadListSP section_load_list_sp(new SectionLoadList());
+ if (stop_id == eStopIDNow)
+ stop_id = 0;
+ m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
+ return section_load_list_sp.get();
}
SectionLoadList &
SectionLoadHistory::GetCurrentSectionLoadList ()
{
const bool read_only = true;
+ Mutex::Locker locker(m_mutex);
SectionLoadList *section_load_list = GetSectionLoadListForStopID (eStopIDNow, read_only);
assert(section_load_list != NULL);
return *section_load_list;
diff --git a/source/Target/SectionLoadList.cpp b/source/Target/SectionLoadList.cpp
index 82f52f9db1b5..da3aea5034d1 100644
--- a/source/Target/SectionLoadList.cpp
+++ b/source/Target/SectionLoadList.cpp
@@ -81,19 +81,17 @@ SectionLoadList::SetSectionLoadAddress (const lldb::SectionSP &section, addr_t l
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
ModuleSP module_sp (section->GetModule());
-
+
if (module_sp)
{
if (log)
{
const FileSpec &module_file_spec (module_sp->GetFileSpec());
log->Printf ("SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64 ") module = %p",
- __FUNCTION__,
- section.get(),
+ __FUNCTION__, static_cast<void*>(section.get()),
module_file_spec.GetPath().c_str(),
- section->GetName().AsCString(),
- load_addr,
- module_sp.get());
+ section->GetName().AsCString(), load_addr,
+ static_cast<void*>(module_sp.get()));
}
if (section->GetByteSize() == 0)
@@ -118,7 +116,7 @@ SectionLoadList::SetSectionLoadAddress (const lldb::SectionSP &section, addr_t l
{
// Some sections are ok to overlap, and for others we should warn. When
// we have multiple load addresses that correspond to a section, we will
- // allways attribute the section to the be last section that claims it
+ // always attribute the section to the be last section that claims it
// exists at that address. Sometimes it is ok for more that one section
// to be loaded at a specific load address, and other times it isn't.
// The "warn_multiple" parameter tells us if we should warn in this case
@@ -155,8 +153,7 @@ SectionLoadList::SetSectionLoadAddress (const lldb::SectionSP &section, addr_t l
if (log)
{
log->Printf ("SectionLoadList::%s (section = %p (%s), load_addr = 0x%16.16" PRIx64 ") error: module has been deleted",
- __FUNCTION__,
- section.get(),
+ __FUNCTION__, static_cast<void*>(section.get()),
section->GetName().AsCString(),
load_addr);
}
@@ -177,14 +174,13 @@ SectionLoadList::SetSectionUnloaded (const lldb::SectionSP &section_sp)
{
const FileSpec &module_file_spec (section_sp->GetModule()->GetFileSpec());
log->Printf ("SectionLoadList::%s (section = %p (%s.%s))",
- __FUNCTION__,
- section_sp.get(),
+ __FUNCTION__, static_cast<void*>(section_sp.get()),
module_file_spec.GetPath().c_str(),
section_sp->GetName().AsCString());
}
Mutex::Locker locker(m_mutex);
-
+
sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section_sp.get());
if (sta_pos != m_sect_to_addr.end())
{
@@ -209,11 +205,9 @@ SectionLoadList::SetSectionUnloaded (const lldb::SectionSP &section_sp, addr_t l
{
const FileSpec &module_file_spec (section_sp->GetModule()->GetFileSpec());
log->Printf ("SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64 ")",
- __FUNCTION__,
- section_sp.get(),
+ __FUNCTION__, static_cast<void*>(section_sp.get()),
module_file_spec.GetPath().c_str(),
- section_sp->GetName().AsCString(),
- load_addr);
+ section_sp->GetName().AsCString(), load_addr);
}
bool erased = false;
Mutex::Locker locker(m_mutex);
@@ -223,7 +217,7 @@ SectionLoadList::SetSectionUnloaded (const lldb::SectionSP &section_sp, addr_t l
erased = true;
m_sect_to_addr.erase (sta_pos);
}
-
+
addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
if (ats_pos != m_addr_to_sect.end())
{
@@ -287,7 +281,8 @@ SectionLoadList::Dump (Stream &s, Target *target)
addr_to_sect_collection::const_iterator pos, end;
for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end; ++pos)
{
- s.Printf("addr = 0x%16.16" PRIx64 ", section = %p: ", pos->first, pos->second.get());
+ s.Printf("addr = 0x%16.16" PRIx64 ", section = %p: ",
+ pos->first, static_cast<void*>(pos->second.get()));
pos->second->Dump (&s, target, 0);
}
}
diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp
index a936a57d048d..e497b176ccfe 100644
--- a/source/Target/StackFrame.cpp
+++ b/source/Target/StackFrame.cpp
@@ -360,7 +360,7 @@ StackFrame::GetSymbolContext (uint32_t resolve_scope)
}
- // Resolve our PC to section offset if we haven't alreday done so
+ // Resolve our PC to section offset if we haven't already done so
// and if we don't have a module. The resolved address section will
// contain the module to which it belongs
if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR))
@@ -861,7 +861,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
valobj_sp->GetTypeName().AsCString("<invalid type>"),
var_expr_path_strm.GetString().c_str());
}
- else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
+ else if (static_cast<uint32_t>(child_index) >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
{
valobj_sp->GetExpressionPath (var_expr_path_strm, false);
error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"",
@@ -937,7 +937,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
valobj_sp->GetTypeName().AsCString("<invalid type>"),
var_expr_path_strm.GetString().c_str());
}
- else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
+ else if (static_cast<uint32_t>(child_index) >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
{
valobj_sp->GetExpressionPath (var_expr_path_strm, false);
error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"",
@@ -1444,13 +1444,12 @@ StackFrame::GetStatus (Stream& strm,
const uint32_t source_lines_after = debugger.GetStopSourceLineCount(false);
disasm_display = debugger.GetStopDisassemblyDisplay ();
- if (source_lines_before > 0 || source_lines_after > 0)
+ GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);
+ if (m_sc.comp_unit && m_sc.line_entry.IsValid())
{
- GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);
-
- if (m_sc.comp_unit && m_sc.line_entry.IsValid())
+ have_source = true;
+ if (source_lines_before > 0 || source_lines_after > 0)
{
- have_source = true;
target->GetSourceManager().DisplaySourceLinesWithLineNumbers (m_sc.line_entry.file,
m_sc.line_entry.line,
source_lines_before,
diff --git a/source/Target/StackFrameList.cpp b/source/Target/StackFrameList.cpp
index 631a77bd4951..99234dc61f1d 100644
--- a/source/Target/StackFrameList.cpp
+++ b/source/Target/StackFrameList.cpp
@@ -269,7 +269,7 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx)
StreamFile s(stdout, false);
#endif
// If we are hiding some frames from the outside world, we need to add those onto the total count of
- // frames to fetch. However, we don't need ot do that if end_idx is 0 since in that case we always
+ // frames to fetch. However, we don't need to do that if end_idx is 0 since in that case we always
// get the first concrete frame and all the inlined frames below it... And of course, if end_idx is
// UINT32_MAX that means get all, so just do that...
@@ -491,7 +491,7 @@ StackFrameList::Dump (Stream *s)
for (pos = begin; pos != end; ++pos)
{
StackFrame *frame = (*pos).get();
- s->Printf("%p: ", frame);
+ s->Printf("%p: ", static_cast<void*>(frame));
if (frame)
{
frame->GetStackID().Dump (s);
diff --git a/source/Target/StackID.cpp b/source/Target/StackID.cpp
index 9e8c315d0704..ca337f914406 100644
--- a/source/Target/StackID.cpp
+++ b/source/Target/StackID.cpp
@@ -24,11 +24,12 @@ using namespace lldb_private;
void
StackID::Dump (Stream *s)
{
- s->Printf("StackID (pc = 0x%16.16" PRIx64 ", cfa = 0x%16.16" PRIx64 ", symbol_scope = %p", (uint64_t)m_pc, (uint64_t)m_cfa, m_symbol_scope);
+ s->Printf("StackID (pc = 0x%16.16" PRIx64 ", cfa = 0x%16.16" PRIx64 ", symbol_scope = %p",
+ m_pc, m_cfa, static_cast<void*>(m_symbol_scope));
if (m_symbol_scope)
{
SymbolContext sc;
-
+
m_symbol_scope->CalculateSymbolContext (&sc);
if (sc.block)
s->Printf(" (Block {0x%8.8" PRIx64 "})", sc.block->GetID());
diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp
index 3664e8f0c738..a37a4079ff11 100644
--- a/source/Target/StopInfo.cpp
+++ b/source/Target/StopInfo.cpp
@@ -108,7 +108,6 @@ namespace lldb_private
class StopInfoBreakpoint : public StopInfo
{
public:
-
StopInfoBreakpoint (Thread &thread, break_id_t break_id) :
StopInfo (thread, break_id),
m_description(),
@@ -121,7 +120,7 @@ public:
{
StoreBPInfo();
}
-
+
StopInfoBreakpoint (Thread &thread, break_id_t break_id, bool should_stop) :
StopInfo (thread, break_id),
m_description(),
@@ -161,7 +160,7 @@ public:
virtual ~StopInfoBreakpoint ()
{
}
-
+
virtual StopReason
GetStopReason () const
{
@@ -199,7 +198,7 @@ public:
}
return false;
}
-
+
virtual bool
DoShouldNotify (Event *event_ptr)
{
@@ -252,7 +251,7 @@ public:
}
}
}
-
+
strm.Printf("breakpoint ");
bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief);
m_description.swap (strm.GetString());
@@ -290,7 +289,7 @@ public:
strm.Printf("breakpoint site %" PRIi64 " which has been deleted - unknown address", m_value);
else
strm.Printf("breakpoint site %" PRIi64 " which has been deleted - was at 0x%" PRIx64, m_value, m_address);
-
+
m_description.swap (strm.GetString());
}
}
@@ -307,20 +306,20 @@ protected:
assert (m_should_stop_is_valid);
return m_should_stop;
}
-
+
virtual void
PerformAction (Event *event_ptr)
{
if (!m_should_perform_action)
return;
m_should_perform_action = false;
-
+
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)
{
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
-
+ Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS | LIBLLDB_LOG_STEP);
+
if (!thread_sp->IsValid())
{
// This shouldn't ever happen, but just in case, don't do more harm.
@@ -332,13 +331,13 @@ protected:
m_should_stop_is_valid = true;
return;
}
-
+
BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value));
-
+
if (bp_site_sp)
{
size_t num_owners = bp_site_sp->GetNumberOfOwners();
-
+
if (num_owners == 0)
{
m_should_stop = true;
@@ -354,7 +353,7 @@ protected:
// we're going to restart, without running the rest of the callbacks. And in this case we will
// end up not stopping even if another location said we should stop. But that's better than not
// running all the callbacks.
-
+
m_should_stop = false;
ExecutionContext exe_ctx (thread_sp->GetStackFrameAtIndex(0));
@@ -367,7 +366,7 @@ protected:
// TODO: We can keep a list of the breakpoints we've seen while running expressions in the nested
// PerformAction calls that can arise when the action runs a function that hits another breakpoint,
// and only stop running commands when we see the same breakpoint hit a second time.
-
+
m_should_stop_is_valid = true;
if (log)
log->Printf ("StopInfoBreakpoint::PerformAction - Hit a breakpoint while running an expression,"
@@ -398,12 +397,12 @@ protected:
"running function, skipping commands and conditions to prevent recursion.");
return;
}
-
+
StoppointCallbackContext context (event_ptr, exe_ctx, false);
-
+
// 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.
-
+
BreakpointLocationCollection site_locations;
for (size_t j = 0; j < num_owners; j++)
site_locations.Add(bp_site_sp->GetOwnerAtIndex(j));
@@ -411,11 +410,11 @@ protected:
for (size_t j = 0; j < num_owners; j++)
{
lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j);
-
+
// If another action disabled this breakpoint or its location, then don't run the actions.
if (!bp_loc_sp->IsEnabled() || !bp_loc_sp->GetBreakpoint().IsEnabled())
continue;
-
+
// The breakpoint site may have many locations associated with it, not all of them valid for
// this thread. Skip the ones that aren't:
if (!bp_loc_sp->ValidForThisThread(thread_sp.get()))
@@ -424,18 +423,20 @@ protected:
{
StreamString s;
bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief);
- log->Printf ("Breakpoint %s hit on thread 0x%llx but it was not for this thread, continuing.", s.GetData(), thread_sp->GetID());
+ log->Printf ("Breakpoint %s hit on thread 0x%llx but it was not for this thread, continuing.",
+ s.GetData(),
+ static_cast<unsigned long long>(thread_sp->GetID()));
}
continue;
}
// First run the condition for the breakpoint. If that says we should stop, then we'll run
// the callback for the breakpoint. If the callback says we shouldn't stop that will win.
-
+
if (bp_loc_sp->GetConditionText() != NULL)
{
Error condition_error;
bool condition_says_stop = bp_loc_sp->ConditionSaysStop(exe_ctx, condition_error);
-
+
if (!condition_error.Success())
{
Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
@@ -448,12 +449,10 @@ protected:
const char *err_str = condition_error.AsCString("<Unknown Error>");
if (log)
log->Printf("Error evaluating condition: \"%s\"\n", err_str);
-
+
error_sp->PutCString (err_str);
error_sp->EOL();
error_sp->Flush();
- // If the condition fails to be parsed or run, we should stop.
- condition_says_stop = true;
}
else
{
@@ -461,36 +460,39 @@ protected:
{
StreamString s;
bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief);
- log->Printf ("Condition evaluated for breakpoint %s on thread 0x%llx conditon_says_stop: %i.", s.GetData(), thread_sp->GetID(), condition_says_stop);
+ log->Printf ("Condition evaluated for breakpoint %s on thread 0x%llx conditon_says_stop: %i.",
+ s.GetData(),
+ static_cast<unsigned long long>(thread_sp->GetID()),
+ condition_says_stop);
}
if (!condition_says_stop)
continue;
}
}
-
+
bool callback_says_stop;
-
+
// FIXME: For now the callbacks have to run in async mode - the first time we restart we need
// to get out of there. So set it here.
// When we figure out how to nest breakpoint hits then this will change.
-
+
Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger();
bool old_async = debugger.GetAsyncExecution();
debugger.SetAsyncExecution (true);
-
+
callback_says_stop = bp_loc_sp->InvokeCallback (&context);
-
+
debugger.SetAsyncExecution (old_async);
-
+
if (callback_says_stop)
m_should_stop = true;
-
+
// If we are going to stop for this breakpoint, then remove the breakpoint.
if (callback_says_stop && bp_loc_sp && bp_loc_sp->GetBreakpoint().IsOneShot())
{
thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID (bp_loc_sp->GetBreakpoint().GetID());
}
-
+
// Also make sure that the callback hasn't continued the target.
// If it did, when we'll set m_should_start to false and get out of here.
if (HasTargetRunSinceMe ())
@@ -706,7 +708,7 @@ protected:
{
// We need to make sure the user sees any parse errors in their condition, so we'll hook the
// constructor errors up to the debugger's Async I/O.
- ExecutionResults result_code;
+ ExpressionResults result_code;
EvaluateExpressionOptions expr_options;
expr_options.SetUnwindOnError(true);
expr_options.SetIgnoreBreakpoints(true);
@@ -718,7 +720,7 @@ protected:
NULL,
result_value_sp,
error);
- if (result_code == eExecutionCompleted)
+ if (result_code == eExpressionCompleted)
{
if (result_value_sp)
{
@@ -995,10 +997,11 @@ class StopInfoThreadPlan : public StopInfo
{
public:
- StopInfoThreadPlan (ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp) :
+ StopInfoThreadPlan (ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp, ClangExpressionVariableSP &expression_variable_sp) :
StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID),
m_plan_sp (plan_sp),
- m_return_valobj_sp (return_valobj_sp)
+ m_return_valobj_sp (return_valobj_sp),
+ m_expression_variable_sp (expression_variable_sp)
{
}
@@ -1030,6 +1033,12 @@ public:
return m_return_valobj_sp;
}
+ ClangExpressionVariableSP
+ GetExpressionVariable()
+ {
+ return m_expression_variable_sp;
+ }
+
protected:
virtual bool
ShouldStop (Event *event_ptr)
@@ -1043,6 +1052,7 @@ protected:
private:
ThreadPlanSP m_plan_sp;
ValueObjectSP m_return_valobj_sp;
+ ClangExpressionVariableSP m_expression_variable_sp;
};
class StopInfoExec : public StopInfo
@@ -1121,9 +1131,11 @@ StopInfo::CreateStopReasonToTrace (Thread &thread)
}
StopInfoSP
-StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp, ValueObjectSP return_valobj_sp)
+StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp,
+ ValueObjectSP return_valobj_sp,
+ ClangExpressionVariableSP expression_variable_sp)
{
- return StopInfoSP (new StopInfoThreadPlan (plan_sp, return_valobj_sp));
+ return StopInfoSP (new StopInfoThreadPlan (plan_sp, return_valobj_sp, expression_variable_sp));
}
StopInfoSP
@@ -1149,3 +1161,15 @@ StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp)
else
return ValueObjectSP();
}
+
+ClangExpressionVariableSP
+StopInfo::GetExpressionVariable(StopInfoSP &stop_info_sp)
+{
+ if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonPlanComplete)
+ {
+ StopInfoThreadPlan *plan_stop_info = static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
+ return plan_stop_info->GetExpressionVariable();
+ }
+ else
+ return ClangExpressionVariableSP();
+}
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index e7816266b415..d2d0b5098555 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -94,12 +94,12 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
SetEventName (eBroadcastBitModulesUnloaded, "modules-unloaded");
SetEventName (eBroadcastBitWatchpointChanged, "watchpoint-changed");
SetEventName (eBroadcastBitSymbolsLoaded, "symbols-loaded");
-
+
CheckInWithManager();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p Target::Target()", this);
+ log->Printf ("%p Target::Target()", static_cast<void*>(this));
if (m_arch.IsValid())
{
LogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET, "Target::Target created with architecture %s (%s)", m_arch.GetArchitectureName(), m_arch.GetTriple().getTriple().c_str());
@@ -113,7 +113,7 @@ Target::~Target()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p Target::~Target()", this);
+ log->Printf ("%p Target::~Target()", static_cast<void*>(this));
DeleteCurrentProcess ();
}
@@ -486,9 +486,12 @@ Target::CreateFuncRegexBreakpoint (const FileSpecList *containingModules,
bool hardware)
{
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, containingSourceFiles));
+ bool skip =
+ (skip_prologue == eLazyBoolCalculate) ? GetSkipPrologue()
+ : static_cast<bool>(skip_prologue);
BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL,
func_regex,
- skip_prologue == eLazyBoolCalculate ? GetSkipPrologue() : skip_prologue));
+ skip));
return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
@@ -635,7 +638,7 @@ Target::CreateWatchpoint(lldb::addr_t addr, size_t size, const ClangASTType *typ
if (!CheckIfWatchpointsExhausted(this, error))
{
if (!OptionGroupWatchpoint::IsWatchSizeSupported(size))
- error.SetErrorStringWithFormat("watch size of %zu is not supported", size);
+ error.SetErrorStringWithFormat("watch size of %" PRIu64 " is not supported", (uint64_t)size);
}
wp_sp.reset();
}
@@ -1010,10 +1013,10 @@ LoadScriptingResourceForModule (const ModuleSP &module_sp, Target *target)
target->GetDebugger().GetErrorFile()->Printf("unable to load scripting data for module %s - error reported was %s\n",
module_sp->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
error.AsCString());
- if (feedback_stream.GetSize())
- target->GetDebugger().GetErrorFile()->Printf("%s\n",
- feedback_stream.GetData());
}
+ if (feedback_stream.GetSize())
+ target->GetDebugger().GetErrorFile()->Printf("%s\n",
+ feedback_stream.GetData());
}
void
@@ -1047,7 +1050,7 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
"Target::SetExecutableModule (executable = '%s')",
executable_sp->GetFileSpec().GetPath().c_str());
- m_images.Append(executable_sp); // The first image is our exectuable file
+ m_images.Append(executable_sp); // The first image is our executable file
// If we haven't set an architecture yet, reset our architecture based on what we found in the executable module.
if (!m_arch.IsValid())
@@ -1142,41 +1145,44 @@ void
Target::ModuleAdded (const ModuleList& module_list, const ModuleSP &module_sp)
{
// A module is being added to this target for the first time
- ModuleList my_module_list;
- my_module_list.Append(module_sp);
- LoadScriptingResourceForModule(module_sp, this);
- ModulesDidLoad (my_module_list);
+ if (m_valid)
+ {
+ ModuleList my_module_list;
+ my_module_list.Append(module_sp);
+ LoadScriptingResourceForModule(module_sp, this);
+ ModulesDidLoad (my_module_list);
+ }
}
void
Target::ModuleRemoved (const ModuleList& module_list, const ModuleSP &module_sp)
{
// A module is being added to this target for the first time
- ModuleList my_module_list;
- my_module_list.Append(module_sp);
- ModulesDidUnload (my_module_list, false);
+ if (m_valid)
+ {
+ ModuleList my_module_list;
+ my_module_list.Append(module_sp);
+ ModulesDidUnload (my_module_list, false);
+ }
}
void
Target::ModuleUpdated (const ModuleList& module_list, const ModuleSP &old_module_sp, const ModuleSP &new_module_sp)
{
// A module is replacing an already added module
- m_breakpoint_list.UpdateBreakpointsWhenModuleIsReplaced(old_module_sp, new_module_sp);
+ if (m_valid)
+ m_breakpoint_list.UpdateBreakpointsWhenModuleIsReplaced(old_module_sp, new_module_sp);
}
void
Target::ModulesDidLoad (ModuleList &module_list)
{
- if (module_list.GetSize())
+ if (m_valid && module_list.GetSize())
{
m_breakpoint_list.UpdateBreakpoints (module_list, true, false);
if (m_process_sp)
{
- SystemRuntime *sys_runtime = m_process_sp->GetSystemRuntime();
- if (sys_runtime)
- {
- sys_runtime->ModulesDidLoad (module_list);
- }
+ m_process_sp->ModulesDidLoad (module_list);
}
// TODO: make event data that packages up the module_list
BroadcastEvent (eBroadcastBitModulesLoaded, NULL);
@@ -1186,7 +1192,7 @@ Target::ModulesDidLoad (ModuleList &module_list)
void
Target::SymbolsDidLoad (ModuleList &module_list)
{
- if (module_list.GetSize())
+ if (m_valid && module_list.GetSize())
{
if (m_process_sp)
{
@@ -1206,7 +1212,7 @@ Target::SymbolsDidLoad (ModuleList &module_list)
void
Target::ModulesDidUnload (ModuleList &module_list, bool delete_locations)
{
- if (module_list.GetSize())
+ if (m_valid && module_list.GetSize())
{
m_breakpoint_list.UpdateBreakpoints (module_list, false, delete_locations);
// TODO: make event data that packages up the module_list
@@ -1255,7 +1261,7 @@ Target::ReadMemoryFromFileCache (const Address& addr, void *dst, size_t dst_len,
SectionSP section_sp (addr.GetSection());
if (section_sp)
{
- // If the contents of this section are encrypted, the on-disk file is unusuable. Read only from live memory.
+ // If the contents of this section are encrypted, the on-disk file is unusable. Read only from live memory.
if (section_sp->IsEncrypted())
{
error.SetErrorString("section is encrypted");
@@ -1320,7 +1326,7 @@ Target::ReadMemory (const Address& addr,
}
else
{
- // We have at least one section loaded. This can be becuase
+ // We have at least one section loaded. This can be because
// we have manually loaded some sections with "target modules load ..."
// or because we have have a live process that has sections loaded
// through the dynamic loader
@@ -1376,7 +1382,7 @@ Target::ReadMemory (const Address& addr,
}
// If the address is not section offset we have an address that
// doesn't resolve to any address in any currently loaded shared
- // libaries and we failed to read memory so there isn't anything
+ // libraries and we failed to read memory so there isn't anything
// more we can do. If it is section offset, we might be able to
// read cached memory from the object file.
if (!resolved_addr.IsSectionOffset())
@@ -1547,7 +1553,7 @@ Target::ReadPointerFromMemory (const Address& addr,
}
else
{
- // We have at least one section loaded. This can be becuase
+ // We have at least one section loaded. This can be because
// we have manually loaded some sections with "target modules load ..."
// or because we have have a live process that has sections loaded
// through the dynamic loader
@@ -1698,6 +1704,8 @@ Target::GetSharedModule (const ModuleSpec &module_spec, Error *error_ptr)
else
m_images.Append(module_sp);
}
+ else
+ module_sp.reset();
}
}
if (error_ptr)
@@ -1765,7 +1773,7 @@ Target::GetScratchClangASTContext(bool create_on_demand)
m_scratch_ast_context_ap.reset (new ClangASTContext(m_arch.GetTriple().str().c_str()));
m_scratch_ast_source_ap.reset (new ClangASTSource(shared_from_this()));
m_scratch_ast_source_ap->InstallASTContext(m_scratch_ast_context_ap->getASTContext());
- llvm::OwningPtr<clang::ExternalASTSource> proxy_ast_source(m_scratch_ast_source_ap->CreateProxy());
+ llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(m_scratch_ast_source_ap->CreateProxy());
m_scratch_ast_context_ap->SetExternalSource(proxy_ast_source);
}
return m_scratch_ast_context_ap.get();
@@ -1850,7 +1858,7 @@ Target::GetTargetFromContexts (const ExecutionContext *exe_ctx_ptr, const Symbol
return target;
}
-ExecutionResults
+ExpressionResults
Target::EvaluateExpression
(
const char *expr_cstr,
@@ -1861,7 +1869,7 @@ Target::EvaluateExpression
{
result_valobj_sp.reset();
- ExecutionResults execution_results = eExecutionSetupError;
+ ExpressionResults execution_results = eExpressionSetupError;
if (expr_cstr == NULL || expr_cstr[0] == '\0')
return execution_results;
@@ -1896,7 +1904,7 @@ Target::EvaluateExpression
if (persistent_var_sp)
{
result_valobj_sp = persistent_var_sp->GetValueObject ();
- execution_results = eExecutionCompleted;
+ execution_results = eExpressionCompleted;
}
else
{
@@ -2363,7 +2371,8 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
if (!launch_info.GetArchitecture().IsValid())
launch_info.GetArchitecture() = GetArchitecture();
-
+
+ // 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 ())
{
m_process_sp = GetPlatform()->DebugProcess (launch_info,
@@ -2380,10 +2389,12 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
}
else
{
+ // Use a Process plugin to construct the process.
const char *plugin_name = launch_info.GetProcessPluginName();
CreateProcess (listener, plugin_name, NULL);
}
-
+
+ // Since we didn't have a platform launch the process, launch it here.
if (m_process_sp)
error = m_process_sp->Launch (launch_info);
}
@@ -2409,9 +2420,14 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
m_process_sp->RestoreProcessEvents ();
error = m_process_sp->PrivateResume();
-
+
if (error.Success())
{
+ // 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
+ // a chance to call PushProcessIOHandler()
+ m_process_sp->SyncIOHandler(2000);
+
if (synchronous_execution)
{
state = m_process_sp->WaitForProcessToStop (NULL, NULL, true, hijack_listener_sp.get());
@@ -2429,6 +2445,27 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
error = error2;
}
}
+ else if (state == eStateExited)
+ {
+ 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'."
+ if (exit_desc && exit_desc[0])
+ {
+ if (with_shell)
+ error.SetErrorStringWithFormat ("process exited with status %i (%s)" LAUNCH_SHELL_MESSAGE, exit_status, exit_desc);
+ else
+ error.SetErrorStringWithFormat ("process exited with status %i (%s)", exit_status, exit_desc);
+ }
+ else
+ {
+ if (with_shell)
+ error.SetErrorStringWithFormat ("process exited with status %i" LAUNCH_SHELL_MESSAGE, exit_status);
+ else
+ error.SetErrorStringWithFormat ("process exited with status %i", exit_status);
+ }
+ }
else
{
error.SetErrorStringWithFormat ("initial process state wasn't stopped: %s", StateAsCString(state));
@@ -2616,6 +2653,7 @@ g_properties[] =
{ "input-path" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "The file/path to be used by the executable program for reading its standard input." },
{ "output-path" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "The file/path to be used by the executable program for writing its standard output." },
{ "error-path" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "The file/path to be used by the executable program for writing its standard error." },
+ { "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. "
@@ -2662,6 +2700,7 @@ enum
ePropertyInputPath,
ePropertyOutputPath,
ePropertyErrorPath,
+ ePropertyDetachOnError,
ePropertyDisableASLR,
ePropertyDisableSTDIO,
ePropertyInlineStrategy,
@@ -2699,7 +2738,7 @@ public:
virtual const Property *
GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
{
- // When gettings the value for a key from the target options, we will always
+ // When getting the value for a key from the target options, we will always
// try and grab the setting from the current target if there is one. Else we just
// use the one from this instance.
if (idx == ePropertyEnvVars)
@@ -2845,6 +2884,20 @@ TargetProperties::SetDisableASLR (bool b)
}
bool
+TargetProperties::GetDetachOnError () const
+{
+ const uint32_t idx = ePropertyDetachOnError;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+void
+TargetProperties::SetDetachOnError (bool b)
+{
+ const uint32_t idx = ePropertyDetachOnError;
+ m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
+}
+
+bool
TargetProperties::GetDisableSTDIO () const
{
const uint32_t idx = ePropertyDisableSTDIO;
diff --git a/source/Target/TargetList.cpp b/source/Target/TargetList.cpp
index c4da84fbf8be..5ee75ff74449 100644
--- a/source/Target/TargetList.cpp
+++ b/source/Target/TargetList.cpp
@@ -28,6 +28,8 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/TargetList.h"
+#include "llvm/ADT/SmallString.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -85,12 +87,31 @@ TargetList::CreateTarget (Debugger &debugger,
ArchSpec platform_arch(arch);
+ bool prefer_platform_arch = false;
+
+ CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
+ if (platform_options && platform_options->PlatformWasSpecified ())
+ {
+ const bool select_platform = true;
+ platform_sp = platform_options->CreatePlatformWithOptions (interpreter,
+ arch,
+ select_platform,
+ error,
+ platform_arch);
+ if (!platform_sp)
+ return error;
+ }
if (user_exe_path && user_exe_path[0])
{
ModuleSpecList module_specs;
ModuleSpec module_spec;
module_spec.GetFileSpec().SetFile(user_exe_path, true);
+
+ // Resolve the executable in case we are given a path to a application bundle
+ // like a .app bundle on MacOSX
+ Host::ResolveExecutableInBundle (module_spec.GetFileSpec());
+
lldb::offset_t file_offset = 0;
lldb::offset_t file_size = 0;
const size_t num_specs = ObjectFile::GetModuleSpecifications (module_spec.GetFileSpec(), file_offset, file_size, module_specs);
@@ -104,7 +125,17 @@ TargetList::CreateTarget (Debugger &debugger,
{
if (platform_arch.IsValid())
{
- if (!platform_arch.IsCompatibleMatch(matching_module_spec.GetArchitecture()))
+ if (platform_arch.IsCompatibleMatch(matching_module_spec.GetArchitecture()))
+ {
+ // If the OS or vendor weren't specified, then adopt the module's
+ // architecture so that the platform matching can be more accurate
+ if (!platform_arch.TripleOSWasSpecified() || !platform_arch.TripleVendorWasSpecified())
+ {
+ prefer_platform_arch = true;
+ platform_arch = matching_module_spec.GetArchitecture();
+ }
+ }
+ else
{
error.SetErrorStringWithFormat("the specified architecture '%s' is not compatible with '%s' in '%s'",
platform_arch.GetTriple().str().c_str(),
@@ -116,6 +147,7 @@ TargetList::CreateTarget (Debugger &debugger,
else
{
// Only one arch and none was specified
+ prefer_platform_arch = true;
platform_arch = matching_module_spec.GetArchitecture();
}
}
@@ -127,48 +159,114 @@ TargetList::CreateTarget (Debugger &debugger,
module_spec.GetArchitecture() = arch;
if (module_specs.FindMatchingModuleSpec(module_spec, matching_module_spec))
{
+ prefer_platform_arch = true;
platform_arch = matching_module_spec.GetArchitecture();
}
}
- // Don't just select the first architecture, we want to let the platform select
- // the best architecture first when there are multiple archs.
-// else
-// {
-// // No arch specified, select the first arch
-// if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec))
-// {
-// platform_arch = matching_module_spec.GetArchitecture();
-// }
-// }
+ else
+ {
+ // No architecture specified, check if there is only one platform for
+ // all of the architectures.
+
+ typedef std::vector<PlatformSP> PlatformList;
+ PlatformList platforms;
+ PlatformSP host_platform_sp = Platform::GetDefaultPlatform();
+ for (size_t i=0; i<num_specs; ++i)
+ {
+ ModuleSpec module_spec;
+ if (module_specs.GetModuleSpecAtIndex(i, module_spec))
+ {
+ // See if there was a selected platform and check that first
+ // since the user may have specified it.
+ if (platform_sp)
+ {
+ if (platform_sp->IsCompatibleArchitecture(module_spec.GetArchitecture(), false, NULL))
+ {
+ platforms.push_back(platform_sp);
+ continue;
+ }
+ }
+
+ // Next check the host platform it if wasn't already checked above
+ if (host_platform_sp && (!platform_sp || host_platform_sp->GetName() != platform_sp->GetName()))
+ {
+ if (host_platform_sp->IsCompatibleArchitecture(module_spec.GetArchitecture(), false, NULL))
+ {
+ platforms.push_back(host_platform_sp);
+ continue;
+ }
+ }
+
+ // Just find a platform that matches the architecture in the executable file
+ platforms.push_back(Platform::GetPlatformForArchitecture(module_spec.GetArchitecture(), nullptr));
+ }
+ }
+
+ Platform *platform_ptr = NULL;
+ for (const auto &the_platform_sp : platforms)
+ {
+ if (platform_ptr)
+ {
+ if (platform_ptr->GetName() != the_platform_sp->GetName())
+ {
+ platform_ptr = NULL;
+ break;
+ }
+ }
+ else
+ {
+ platform_ptr = the_platform_sp.get();
+ }
+ }
+
+ if (platform_ptr)
+ {
+ // All platforms for all modules in the exectuable match, so we can select this platform
+ platform_sp = platforms.front();
+ }
+ else
+ {
+ // More than one platform claims to support this file, so the --platform option must be specified
+ StreamString error_strm;
+ std::set<Platform *> platform_set;
+ error_strm.Printf ("more than one platform supports this executable (");
+ for (const auto &the_platform_sp : platforms)
+ {
+ if (platform_set.find(the_platform_sp.get()) == platform_set.end())
+ {
+ if (!platform_set.empty())
+ error_strm.PutCString(", ");
+ error_strm.PutCString(the_platform_sp->GetName().GetCString());
+ platform_set.insert(the_platform_sp.get());
+ }
+ }
+ error_strm.Printf("), use the --platform option to specify a platform");
+ error.SetErrorString(error_strm.GetString().c_str());
+ return error;
+ }
+ }
}
}
}
- CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
- if (platform_options)
- {
- if (platform_options->PlatformWasSpecified ())
- {
- const bool select_platform = true;
- platform_sp = platform_options->CreatePlatformWithOptions (interpreter,
- arch,
- select_platform,
- error,
- platform_arch);
- if (!platform_sp)
- return error;
- }
- }
-
if (!platform_sp)
{
// Get the current platform and make sure it is compatible with the
// current architecture if we have a valid architecture.
platform_sp = debugger.GetPlatformList().GetSelectedPlatform ();
- if (arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch))
+ if (!prefer_platform_arch && arch.IsValid())
{
- platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
+ if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch))
+ platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
+ }
+ else if (platform_arch.IsValid())
+ {
+ // if "arch" isn't valid, yet "platform_arch" is, it means we have an executable file with
+ // 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);
}
}
@@ -200,17 +298,10 @@ TargetList::CreateTarget (Debugger &debugger,
ArchSpec arch(specified_arch);
- if (platform_sp)
+ if (arch.IsValid())
{
- if (arch.IsValid())
- {
- if (!platform_sp->IsCompatibleArchitecture(arch, false, NULL))
- platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
- }
- }
- else if (arch.IsValid())
- {
- platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
+ if (!platform_sp || !platform_sp->IsCompatibleArchitecture(arch, false, NULL))
+ platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
}
if (!platform_sp)
@@ -224,15 +315,13 @@ TargetList::CreateTarget (Debugger &debugger,
{
// we want to expand the tilde but we don't want to resolve any symbolic links
// so we can't use the FileSpec constructor's resolve flag
- char unglobbed_path[PATH_MAX];
- unglobbed_path[0] = '\0';
-
- size_t return_count = FileSpec::ResolveUsername(user_exe_path, unglobbed_path, sizeof(unglobbed_path));
-
- if (return_count == 0 || return_count >= sizeof(unglobbed_path))
- ::snprintf (unglobbed_path, sizeof(unglobbed_path), "%s", user_exe_path);
+ llvm::SmallString<64> unglobbed_path(user_exe_path);
+ FileSpec::ResolveUsername(unglobbed_path);
- file = FileSpec(unglobbed_path, false);
+ if (unglobbed_path.empty())
+ file = FileSpec(user_exe_path, false);
+ else
+ file = FileSpec(unglobbed_path.c_str(), false);
}
bool user_exe_path_is_bundle = false;
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index 39f269952882..a445517da6a8 100644
--- a/source/Target/Thread.cpp
+++ b/source/Target/Thread.cpp
@@ -26,6 +26,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
@@ -61,6 +62,9 @@ Thread::GetGlobalProperties()
static PropertyDefinition
g_properties[] =
{
+ { "step-in-avoid-nodebug", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, step-in will not stop in functions with no debug information." },
+ { "step-out-avoid-nodebug", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, when step-in/step-out/step-over leave the current frame, they will continue to step out till they come to a function with "
+ "debug information. Passing a frame argument to step-out will override this option." },
{ "step-avoid-regexp", OptionValue::eTypeRegex , true , REG_EXTENDED, "^std::", NULL, "A regular expression defining functions step-in won't stop in." },
{ "step-avoid-libraries", OptionValue::eTypeFileSpecList , true , REG_EXTENDED, NULL, NULL, "A list of libraries that source stepping won't stop in." },
{ "trace-thread", OptionValue::eTypeBoolean, false, false, NULL, NULL, "If true, this thread will single-step and log execution." },
@@ -68,6 +72,8 @@ g_properties[] =
};
enum {
+ ePropertyStepInAvoidsNoDebug,
+ ePropertyStepOutAvoidsNoDebug,
ePropertyStepAvoidRegex,
ePropertyStepAvoidLibraries,
ePropertyEnableThreadTrace
@@ -93,7 +99,7 @@ public:
virtual const Property *
GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
{
- // When gettings the value for a key from the thread options, we will always
+ // When getting the value for a key from the thread options, we will always
// try and grab the setting from the current thread if there is one. Else we just
// use the one from this instance.
if (exe_ctx)
@@ -151,6 +157,21 @@ ThreadProperties::GetTraceEnabledState() const
return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
}
+bool
+ThreadProperties::GetStepInAvoidsNoDebug() const
+{
+ const uint32_t idx = ePropertyStepInAvoidsNoDebug;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+bool
+ThreadProperties::GetStepOutAvoidsNoDebug() const
+{
+ const uint32_t idx = ePropertyStepOutAvoidsNoDebug;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+
//------------------------------------------------------------------
// Thread Event Data
//------------------------------------------------------------------
@@ -250,14 +271,14 @@ Thread::GetStaticBroadcasterClass ()
return class_name;
}
-Thread::Thread (Process &process, lldb::tid_t tid) :
+Thread::Thread (Process &process, lldb::tid_t tid, bool use_invalid_index_id) :
ThreadProperties (false),
UserID (tid),
Broadcaster(&process.GetTarget().GetDebugger(), Thread::GetStaticBroadcasterClass().AsCString()),
m_process_wp (process.shared_from_this()),
m_stop_info_sp (),
m_stop_info_stop_id (0),
- m_index_id (process.GetNextThreadIndexID(tid)),
+ m_index_id (use_invalid_index_id ? LLDB_INVALID_INDEX32 : process.GetNextThreadIndexID(tid)),
m_reg_context_sp (),
m_state (eStateUnloaded),
m_state_mutex (Mutex::eMutexTypeRecursive),
@@ -271,11 +292,14 @@ Thread::Thread (Process &process, lldb::tid_t tid) :
m_temporary_resume_state (eStateRunning),
m_unwinder_ap (),
m_destroy_called (false),
- m_override_should_notify (eLazyBoolCalculate)
+ m_override_should_notify (eLazyBoolCalculate),
+ m_extended_info_fetched (false),
+ m_extended_info ()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p Thread::Thread(tid = 0x%4.4" PRIx64 ")", this, GetID());
+ log->Printf ("%p Thread::Thread(tid = 0x%4.4" PRIx64 ")",
+ static_cast<void*>(this), GetID());
CheckInWithManager();
QueueFundamentalPlan(true);
@@ -286,7 +310,8 @@ Thread::~Thread()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("%p Thread::~Thread(tid = 0x%4.4" PRIx64 ")", this, GetID());
+ log->Printf ("%p Thread::~Thread(tid = 0x%4.4" PRIx64 ")",
+ static_cast<void*>(this), GetID());
/// If you hit this assert, it means your derived class forgot to call DoDestroy in its destructor.
assert (m_destroy_called);
}
@@ -395,7 +420,7 @@ Thread::GetStopInfo ()
const uint32_t stop_id = process_sp ? process_sp->GetStopID() : UINT32_MAX;
if (plan_sp && plan_sp->PlanSucceeded())
{
- return StopInfo::CreateStopReasonWithPlan (plan_sp, GetReturnValueObject());
+ return StopInfo::CreateStopReasonWithPlan (plan_sp, GetReturnValueObject(), GetExpressionVariable());
}
else
{
@@ -475,7 +500,10 @@ Thread::SetStopInfo (const lldb::StopInfoSP &stop_info_sp)
m_stop_info_stop_id = UINT32_MAX;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
if (log)
- log->Printf("%p: tid = 0x%" PRIx64 ": stop info = %s (stop_id = %u)\n", this, GetID(), stop_info_sp ? stop_info_sp->GetDescription() : "<NULL>", m_stop_info_stop_id);
+ log->Printf("%p: tid = 0x%" PRIx64 ": stop info = %s (stop_id = %u)",
+ static_cast<void*>(this), GetID(),
+ stop_info_sp ? stop_info_sp->GetDescription() : "<NULL>",
+ m_stop_info_stop_id);
}
void
@@ -723,31 +751,27 @@ bool
Thread::ShouldStop (Event* event_ptr)
{
ThreadPlan *current_plan = GetCurrentPlan();
-
+
bool should_stop = true;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
-
+
if (GetResumeState () == eStateSuspended)
{
if (log)
log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", should_stop = 0 (ignore since thread was suspended)",
- __FUNCTION__,
- GetID (),
- GetProtocolID());
+ __FUNCTION__, GetID (), GetProtocolID());
return false;
}
-
+
if (GetTemporaryResumeState () == eStateSuspended)
{
if (log)
log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", should_stop = 0 (ignore since thread was suspended)",
- __FUNCTION__,
- GetID (),
- GetProtocolID());
+ __FUNCTION__, GetID (), GetProtocolID());
return false;
}
-
+
// Based on the current thread plan and process stop info, check if this
// thread caused the process to stop. NOTE: this must take place before
// the plan is moved from the current plan stack to the completed plan
@@ -756,31 +780,29 @@ Thread::ShouldStop (Event* event_ptr)
{
if (log)
log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", pc = 0x%16.16" PRIx64 ", should_stop = 0 (ignore since no stop reason)",
- __FUNCTION__,
- GetID (),
- GetProtocolID(),
+ __FUNCTION__, GetID (), GetProtocolID(),
GetRegisterContext() ? GetRegisterContext()->GetPC() : LLDB_INVALID_ADDRESS);
return false;
}
-
+
if (log)
{
log->Printf ("Thread::%s(%p) for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", pc = 0x%16.16" PRIx64,
- __FUNCTION__,
- this,
- GetID (),
+ __FUNCTION__, static_cast<void*>(this), GetID (),
GetProtocolID (),
- GetRegisterContext() ? GetRegisterContext()->GetPC() : LLDB_INVALID_ADDRESS);
+ GetRegisterContext()
+ ? GetRegisterContext()->GetPC()
+ : LLDB_INVALID_ADDRESS);
log->Printf ("^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^");
StreamString s;
s.IndentMore();
DumpThreadPlans(&s);
log->Printf ("Plan stack initial state:\n%s", s.GetData());
}
-
+
// The top most plan always gets to do the trace log...
current_plan->DoTraceLog ();
-
+
// First query the stop info's ShouldStopSynchronous. This handles "synchronous" stop reasons, for example the breakpoint
// command on internal breakpoints. If a synchronous stop reason says we should not stop, then we don't have to
// do any more work on this stop.
@@ -823,15 +845,15 @@ Thread::ShouldStop (Event* event_ptr)
if (plan_ptr->PlanExplainsStop(event_ptr))
{
should_stop = plan_ptr->ShouldStop (event_ptr);
-
+
// plan_ptr explains the stop, next check whether plan_ptr is done, if so, then we should take it
// and all the plans below it off the stack.
-
+
if (plan_ptr->MischiefManaged())
{
// We're going to pop the plans up to and including the plan that explains the stop.
ThreadPlan *prev_plan_ptr = GetPreviousPlan (plan_ptr);
-
+
do
{
if (should_stop)
@@ -848,21 +870,22 @@ Thread::ShouldStop (Event* event_ptr)
}
else
done_processing_current_plan = true;
-
+
break;
}
}
}
}
-
+
if (!done_processing_current_plan)
{
bool over_ride_stop = current_plan->ShouldAutoContinue(event_ptr);
-
+
if (log)
- log->Printf("Plan %s explains stop, auto-continue %i.", current_plan->GetName(), over_ride_stop);
-
+ log->Printf("Plan %s explains stop, auto-continue %i.",
+ current_plan->GetName(), over_ride_stop);
+
// We're starting from the base plan, so just let it decide;
if (PlanIsBasePlan(current_plan))
{
@@ -878,10 +901,11 @@ Thread::ShouldStop (Event* event_ptr)
{
if (PlanIsBasePlan(current_plan))
break;
-
+
should_stop = current_plan->ShouldStop(event_ptr);
if (log)
- log->Printf("Plan %s should stop: %d.", current_plan->GetName(), should_stop);
+ log->Printf("Plan %s should stop: %d.",
+ current_plan->GetName(), should_stop);
if (current_plan->MischiefManaged())
{
if (should_stop)
@@ -913,7 +937,7 @@ Thread::ShouldStop (Event* event_ptr)
}
}
}
-
+
if (over_ride_stop)
should_stop = false;
@@ -921,7 +945,7 @@ Thread::ShouldStop (Event* event_ptr)
// 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)
{
ThreadPlan *plan_ptr = GetCurrentPlan();
@@ -930,16 +954,17 @@ Thread::ShouldStop (Event* event_ptr)
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());
+ log->Printf("Plan %s being discarded in cleanup, it says it is already done.",
+ examined_plan->GetName());
DiscardThreadPlansUpToPlan(examined_plan);
}
}
}
-
+
}
if (log)
@@ -1016,37 +1041,33 @@ Vote
Thread::ShouldReportRun (Event* event_ptr)
{
StateType thread_state = GetResumeState ();
-
+
if (thread_state == eStateSuspended
|| thread_state == eStateInvalid)
{
return eVoteNoOpinion;
}
-
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (m_completed_plan_stack.size() > 0)
{
// Don't use GetCompletedPlan here, since that suppresses private plans.
if (log)
log->Printf ("Current Plan for thread %d(%p) (0x%4.4" PRIx64 ", %s): %s being asked whether we should report run.",
- GetIndexID(),
- this,
- GetID(),
+ GetIndexID(), static_cast<void*>(this), GetID(),
StateAsCString(GetTemporaryResumeState()),
m_completed_plan_stack.back()->GetName());
-
+
return m_completed_plan_stack.back()->ShouldReportRun (event_ptr);
}
else
{
if (log)
log->Printf ("Current Plan for thread %d(%p) (0x%4.4" PRIx64 ", %s): %s being asked whether we should report run.",
- GetIndexID(),
- this,
- GetID(),
+ GetIndexID(), static_cast<void*>(this), GetID(),
StateAsCString(GetTemporaryResumeState()),
GetCurrentPlan()->GetName());
-
+
return GetCurrentPlan()->ShouldReportRun (event_ptr);
}
}
@@ -1069,7 +1090,7 @@ Thread::PushPlan (ThreadPlanSP &thread_plan_sp)
if (!thread_plan_sp->GetThreadPlanTracer())
thread_plan_sp->SetThreadPlanTracer(m_plan_stack.back()->GetThreadPlanTracer());
m_plan_stack.push_back (thread_plan_sp);
-
+
thread_plan_sp->DidPush();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
@@ -1078,8 +1099,7 @@ Thread::PushPlan (ThreadPlanSP &thread_plan_sp)
StreamString s;
thread_plan_sp->GetDescription (&s, lldb::eDescriptionLevelFull);
log->Printf("Thread::PushPlan(0x%p): \"%s\", tid = 0x%4.4" PRIx64 ".",
- this,
- s.GetData(),
+ static_cast<void*>(this), s.GetData(),
thread_plan_sp->GetThread().GetID());
}
}
@@ -1164,6 +1184,22 @@ Thread::GetReturnValueObject ()
return ValueObjectSP();
}
+ClangExpressionVariableSP
+Thread::GetExpressionVariable ()
+{
+ if (!m_completed_plan_stack.empty())
+ {
+ for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
+ {
+ ClangExpressionVariableSP expression_variable_sp;
+ expression_variable_sp = m_completed_plan_stack[i]->GetExpressionVariable();
+ if (expression_variable_sp)
+ return expression_variable_sp;
+ }
+ }
+ return ClangExpressionVariableSP();
+}
+
bool
Thread::IsThreadPlanDone (ThreadPlan *plan)
{
@@ -1265,15 +1301,14 @@ Thread::DiscardThreadPlansUpToPlan (ThreadPlan *up_to_plan_ptr)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
- {
- log->Printf("Discarding thread plans for thread tid = 0x%4.4" PRIx64 ", up to %p", GetID(), up_to_plan_ptr);
- }
+ log->Printf("Discarding thread plans for thread tid = 0x%4.4" PRIx64 ", up to %p",
+ GetID(), static_cast<void*>(up_to_plan_ptr));
int stack_size = m_plan_stack.size();
-
+
// If the input plan is NULL, discard all plans. Otherwise make sure this plan is in the
// stack, and if so discard up to and including it.
-
+
if (up_to_plan_ptr == NULL)
{
for (int i = stack_size - 1; i > 0; i--)
@@ -1425,12 +1460,13 @@ Thread::QueueThreadPlanForStepOverRange
bool abort_other_plans,
const AddressRange &range,
const SymbolContext &addr_context,
- lldb::RunMode stop_other_threads
+ lldb::RunMode stop_other_threads,
+ LazyBool step_out_avoids_code_withoug_debug_info
)
{
ThreadPlanSP thread_plan_sp;
- thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads));
-
+ thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads, step_out_avoids_code_withoug_debug_info));
+
QueueThreadPlan (thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
@@ -1443,17 +1479,21 @@ Thread::QueueThreadPlanForStepInRange
const SymbolContext &addr_context,
const char *step_in_target,
lldb::RunMode stop_other_threads,
- bool avoid_code_without_debug_info
+ LazyBool step_in_avoids_code_without_debug_info,
+ LazyBool step_out_avoids_code_without_debug_info
)
{
ThreadPlanSP thread_plan_sp;
- ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this, range, addr_context, stop_other_threads);
- if (avoid_code_without_debug_info)
- plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
- else
- plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
+ ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this,
+ range,
+ addr_context,
+ stop_other_threads,
+ step_in_avoids_code_without_debug_info,
+ step_out_avoids_code_without_debug_info);
+
if (step_in_target)
plan->SetStepInTarget(step_in_target);
+
thread_plan_sp.reset (plan);
QueueThreadPlan (thread_plan_sp, abort_other_plans);
@@ -1470,7 +1510,8 @@ Thread::QueueThreadPlanForStepOut
bool stop_other_threads,
Vote stop_vote,
Vote run_vote,
- uint32_t frame_idx
+ uint32_t frame_idx,
+ LazyBool step_out_avoids_code_withoug_debug_info
)
{
ThreadPlanSP thread_plan_sp (new ThreadPlanStepOut (*this,
@@ -1479,7 +1520,42 @@ Thread::QueueThreadPlanForStepOut
stop_other_threads,
stop_vote,
run_vote,
- frame_idx));
+ frame_idx,
+ step_out_avoids_code_withoug_debug_info));
+
+ if (thread_plan_sp->ValidatePlan(NULL))
+ {
+ QueueThreadPlan (thread_plan_sp, abort_other_plans);
+ return thread_plan_sp;
+ }
+ else
+ {
+ return ThreadPlanSP();
+ }
+}
+
+ThreadPlanSP
+Thread::QueueThreadPlanForStepOutNoShouldStop
+(
+ bool abort_other_plans,
+ SymbolContext *addr_context,
+ bool first_insn,
+ bool stop_other_threads,
+ Vote stop_vote,
+ Vote run_vote,
+ uint32_t frame_idx
+)
+{
+ ThreadPlanStepOut *new_plan = new ThreadPlanStepOut (*this,
+ addr_context,
+ first_insn,
+ stop_other_threads,
+ stop_vote,
+ run_vote,
+ frame_idx,
+ eLazyBoolNo);
+ new_plan->ClearShouldStopHereCallbacks();
+ ThreadPlanSP thread_plan_sp(new_plan);
if (thread_plan_sp->ValidatePlan(NULL))
{
@@ -1651,6 +1727,9 @@ Thread::ClearStackFrames ()
if (m_curr_frames_sp && m_curr_frames_sp->GetAllFramesFetched())
m_prev_frames_sp.swap (m_curr_frames_sp);
m_curr_frames_sp.reset();
+
+ m_extended_info.reset();
+ m_extended_info_fetched = false;
}
lldb::StackFrameSP
@@ -1896,6 +1975,21 @@ Thread::GetThreadLocalData (const ModuleSP module)
return LLDB_INVALID_ADDRESS;
}
+bool
+Thread::SafeToCallFunctions ()
+{
+ Process *process = GetProcess().get();
+ if (process)
+ {
+ SystemRuntime *runtime = process->GetSystemRuntime ();
+ if (runtime)
+ {
+ return runtime->SafeToCallFunctionsOnThisThread (shared_from_this());
+ }
+ }
+ return true;
+}
+
lldb::StackFrameSP
Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
{
@@ -1995,6 +2089,82 @@ Thread::GetStatus (Stream &strm, uint32_t start_frame, uint32_t num_frames, uint
return num_frames_shown;
}
+bool
+Thread::GetDescription (Stream &strm, lldb::DescriptionLevel level, bool print_json)
+{
+ DumpUsingSettingsFormat (strm, 0);
+ strm.Printf("\n");
+
+ StructuredData::ObjectSP thread_info = GetExtendedInfo();
+
+ if (thread_info && print_json)
+ {
+ thread_info->Dump (strm);
+ strm.Printf("\n");
+ return true;
+ }
+
+ if (thread_info)
+ {
+ StructuredData::ObjectSP activity = thread_info->GetObjectForDotSeparatedPath("activity");
+ StructuredData::ObjectSP breadcrumb = thread_info->GetObjectForDotSeparatedPath("breadcrumb");
+ StructuredData::ObjectSP messages = thread_info->GetObjectForDotSeparatedPath("trace_messages");
+
+ bool printed_activity = false;
+ if (activity && activity->GetType() == StructuredData::Type::eTypeDictionary)
+ {
+ StructuredData::Dictionary *activity_dict = activity->GetAsDictionary();
+ StructuredData::ObjectSP id = activity_dict->GetValueForKey("id");
+ StructuredData::ObjectSP name = activity_dict->GetValueForKey("name");
+ if (name && name->GetType() == StructuredData::Type::eTypeString
+ && id && id->GetType() == StructuredData::Type::eTypeInteger)
+ {
+ strm.Printf(" Activity '%s', 0x%" PRIx64 "\n", name->GetAsString()->GetValue().c_str(), id->GetAsInteger()->GetValue());
+ }
+ printed_activity = true;
+ }
+ bool printed_breadcrumb = false;
+ if (breadcrumb && breadcrumb->GetType() == StructuredData::Type::eTypeDictionary)
+ {
+ if (printed_activity)
+ strm.Printf ("\n");
+ StructuredData::Dictionary *breadcrumb_dict = breadcrumb->GetAsDictionary();
+ StructuredData::ObjectSP breadcrumb_text = breadcrumb_dict->GetValueForKey ("name");
+ if (breadcrumb_text && breadcrumb_text->GetType() == StructuredData::Type::eTypeString)
+ {
+ strm.Printf (" Current Breadcrumb: %s\n", breadcrumb_text->GetAsString()->GetValue().c_str());
+ }
+ printed_breadcrumb = true;
+ }
+ if (messages && messages->GetType() == StructuredData::Type::eTypeArray)
+ {
+ if (printed_breadcrumb)
+ strm.Printf("\n");
+ StructuredData::Array *messages_array = messages->GetAsArray();
+ const size_t msg_count = messages_array->GetSize();
+ if (msg_count > 0)
+ {
+ strm.Printf (" %zu trace messages:\n", msg_count);
+ for (size_t i = 0; i < msg_count; i++)
+ {
+ StructuredData::ObjectSP message = messages_array->GetItemAtIndex(i);
+ if (message && message->GetType() == StructuredData::Type::eTypeDictionary)
+ {
+ StructuredData::Dictionary *message_dict = message->GetAsDictionary();
+ StructuredData::ObjectSP message_text = message_dict->GetValueForKey ("message");
+ if (message_text && message_text->GetType() == StructuredData::Type::eTypeString)
+ {
+ strm.Printf (" %s\n", message_text->GetAsString()->GetValue().c_str());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
size_t
Thread::GetStackFrameStatus (Stream& strm,
uint32_t first_frame,
@@ -2021,6 +2191,7 @@ Thread::GetUnwinder ()
case llvm::Triple::x86_64:
case llvm::Triple::x86:
case llvm::Triple::arm:
+ case llvm::Triple::aarch64:
case llvm::Triple::thumb:
case llvm::Triple::mips64:
case llvm::Triple::hexagon:
@@ -2059,7 +2230,8 @@ Thread::IsStillAtLastBreakpointHit ()
{
lldb::addr_t pc = reg_ctx_sp->GetPC();
BreakpointSiteSP bp_site_sp = GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
- if (bp_site_sp && value == bp_site_sp->GetID())
+ if (bp_site_sp &&
+ static_cast<break_id_t>(value) == bp_site_sp->GetID())
return true;
}
}
@@ -2070,8 +2242,9 @@ Thread::IsStillAtLastBreakpointHit ()
Error
Thread::StepIn (bool source_step,
- bool avoid_code_without_debug_info)
-
+ LazyBool step_in_avoids_code_without_debug_info,
+ LazyBool step_out_avoids_code_without_debug_info)
+
{
Error error;
Process *process = GetProcess().get();
@@ -2090,7 +2263,8 @@ Thread::StepIn (bool source_step,
sc,
NULL,
run_mode,
- avoid_code_without_debug_info);
+ step_in_avoids_code_without_debug_info,
+ step_out_avoids_code_without_debug_info);
}
else
{
@@ -2114,8 +2288,8 @@ Thread::StepIn (bool source_step,
}
Error
-Thread::StepOver (bool source_step)
-
+Thread::StepOver (bool source_step,
+ LazyBool step_out_avoids_code_without_debug_info)
{
Error error;
Process *process = GetProcess().get();
@@ -2133,7 +2307,8 @@ Thread::StepOver (bool source_step)
new_plan_sp = QueueThreadPlanForStepOverRange (abort_other_plans,
sc.line_entry.range,
sc,
- run_mode);
+ run_mode,
+ step_out_avoids_code_without_debug_info);
}
else
{
@@ -2187,4 +2362,4 @@ Thread::StepOut ()
error.SetErrorString("process not stopped");
}
return error;
-} \ No newline at end of file
+}
diff --git a/source/Target/ThreadList.cpp b/source/Target/ThreadList.cpp
index 4fffdac9a34e..7fb16fdac5c0 100644
--- a/source/Target/ThreadList.cpp
+++ b/source/Target/ThreadList.cpp
@@ -262,7 +262,7 @@ ThreadList::ShouldStop (Event *event_ptr)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
// The ShouldStop method of the threads can do a whole lot of work,
- // running breakpoint commands & conditions, etc. So we don't want
+ // figuring out whether the thread plan conditions are met. So we don't want
// to keep the ThreadList locked the whole time we are doing this.
// FIXME: It is possible that running code could cause new threads
// to be created. If that happens we will miss asking them whether
@@ -287,7 +287,16 @@ ThreadList::ShouldStop (Event *event_ptr)
}
bool did_anybody_stop_for_a_reason = false;
+
+ // If the event is an Interrupt event, then we're going to stop no matter what. Otherwise, presume we won't stop.
bool should_stop = false;
+ if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr))
+ {
+ if (log)
+ log->Printf("ThreadList::%s handling interrupt event, should stop set to true", __FUNCTION__);
+
+ should_stop = true;
+ }
// Now we run through all the threads and get their stop info's. We want to make sure to do this first before
// we start running the ShouldStop, because one thread's ShouldStop could destroy information (like deleting a
diff --git a/source/Target/ThreadPlan.cpp b/source/Target/ThreadPlan.cpp
index 65d51bd01734..2c9b7fce7c24 100644
--- a/source/Target/ThreadPlan.cpp
+++ b/source/Target/ThreadPlan.cpp
@@ -161,16 +161,11 @@ ThreadPlan::WillResume (StateType resume_state, bool current_plan)
addr_t fp = reg_ctx->GetFP();
log->Printf("%s Thread #%u (0x%p): tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64 ", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", "
"plan = '%s', state = %s, stop others = %d",
- __FUNCTION__,
- m_thread.GetIndexID(),
- &m_thread,
- m_thread.GetID(),
- (uint64_t)pc,
- (uint64_t)sp,
- (uint64_t)fp,
- m_name.c_str(),
- StateAsCString(resume_state),
- StopOthers());
+ __FUNCTION__, m_thread.GetIndexID(),
+ static_cast<void*>(&m_thread), m_thread.GetID(),
+ static_cast<uint64_t>(pc), static_cast<uint64_t>(sp),
+ static_cast<uint64_t>(fp), m_name.c_str(),
+ StateAsCString(resume_state), StopOthers());
}
}
return DoWillResume (resume_state, current_plan);
diff --git a/source/Target/ThreadPlanBase.cpp b/source/Target/ThreadPlanBase.cpp
index 240f23a0b8f4..d70afae55573 100644
--- a/source/Target/ThreadPlanBase.cpp
+++ b/source/Target/ThreadPlanBase.cpp
@@ -151,7 +151,7 @@ ThreadPlanBase::ShouldStop (Event *event_ptr)
// If we crashed, discard thread plans and stop. Don't force the discard, however,
// since on rerun the target may clean up this exception and continue normally from there.
if (log)
- log->Printf("Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 " (exception.)", m_thread.GetID());
+ log->Printf("Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 " (exception: %s)", m_thread.GetID(), stop_info_sp->GetDescription());
m_thread.DiscardThreadPlans(false);
return true;
@@ -168,7 +168,7 @@ ThreadPlanBase::ShouldStop (Event *event_ptr)
if (stop_info_sp->ShouldStop(event_ptr))
{
if (log)
- log->Printf("Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 " (signal.)", m_thread.GetID());
+ log->Printf("Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 " (signal: %s)", m_thread.GetID(), stop_info_sp->GetDescription());
m_thread.DiscardThreadPlans(false);
return true;
}
diff --git a/source/Target/ThreadPlanCallFunction.cpp b/source/Target/ThreadPlanCallFunction.cpp
index 854750b85817..5a3ebd7b1284 100644
--- a/source/Target/ThreadPlanCallFunction.cpp
+++ b/source/Target/ThreadPlanCallFunction.cpp
@@ -12,7 +12,7 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
-#include "llvm/Support/MachO.h"
+
// Project includes
#include "lldb/lldb-private-log.h"
#include "lldb/Breakpoint/Breakpoint.h"
@@ -49,16 +49,16 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
ProcessSP process_sp (thread.GetProcess());
if (!process_sp)
return false;
-
+
abi = process_sp->GetABI().get();
-
+
if (!abi)
return false;
-
+
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
-
+
SetBreakpoints();
-
+
m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
// If we can't read memory at the point of the process where we are planning to put our function, we're
// not going to get any further...
@@ -68,17 +68,21 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
{
m_constructor_errors.Printf ("Trying to put the stack in unreadable memory at: 0x%" PRIx64 ".", m_function_sp);
if (log)
- log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
+ log->Printf ("ThreadPlanCallFunction(%p): %s.",
+ static_cast<void*>(this),
+ m_constructor_errors.GetData());
return false;
}
-
+
Module *exe_module = GetTarget().GetExecutableModulePointer();
if (exe_module == NULL)
{
m_constructor_errors.Printf ("Can't execute code without an executable module.");
if (log)
- log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
+ log->Printf ("ThreadPlanCallFunction(%p): %s.",
+ static_cast<void*>(this),
+ m_constructor_errors.GetData());
return false;
}
else
@@ -90,23 +94,27 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
exe_module->GetFileSpec().GetFilename().AsCString());
if (log)
- log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
+ log->Printf ("ThreadPlanCallFunction(%p): %s.",
+ static_cast<void*>(this),
+ m_constructor_errors.GetData());
return false;
}
-
+
m_start_addr = objectFile->GetEntryPointAddress();
if (!m_start_addr.IsValid())
{
m_constructor_errors.Printf ("Could not find entry point address for executable module \"%s\".",
exe_module->GetFileSpec().GetFilename().AsCString());
if (log)
- log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
+ log->Printf ("ThreadPlanCallFunction(%p): %s.",
+ static_cast<void*>(this),
+ m_constructor_errors.GetData());
return false;
}
}
-
+
start_load_addr = m_start_addr.GetLoadAddress (&GetTarget());
-
+
// Checkpoint the thread state so we can restore it later.
if (log && log->GetVerbose())
ReportRegisterState ("About to checkpoint thread before function call. Original register state was:");
@@ -115,11 +123,13 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
{
m_constructor_errors.Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state.");
if (log)
- log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
+ log->Printf ("ThreadPlanCallFunction(%p): %s.",
+ static_cast<void*>(this),
+ m_constructor_errors.GetData());
return false;
}
function_load_addr = m_function_addr.GetLoadAddress (&GetTarget());
-
+
return true;
}
@@ -148,16 +158,16 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
lldb::addr_t function_load_addr;
if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr))
return;
-
+
if (!abi->PrepareTrivialCall(thread,
m_function_sp,
function_load_addr,
start_load_addr,
args))
return;
-
+
ReportRegisterState ("Function call was set up. Register state was:");
-
+
m_valid = true;
}
@@ -198,15 +208,16 @@ void
ThreadPlanCallFunction::DoTakedown (bool success)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
-
+
if (!m_valid)
{
//Don't call DoTakedown if we were never valid to begin with.
if (log)
- log->Printf ("ThreadPlanCallFunction(%p): Log called on ThreadPlanCallFunction that was never valid.", this);
+ log->Printf ("ThreadPlanCallFunction(%p): Log called on ThreadPlanCallFunction that was never valid.",
+ static_cast<void*>(this));
return;
}
-
+
if (!m_takedown_done)
{
if (success)
@@ -220,14 +231,17 @@ ThreadPlanCallFunction::DoTakedown (bool success)
}
}
if (log)
- log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", this, m_thread.GetID(), m_valid, IsPlanComplete());
+ log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n",
+ static_cast<void*>(this), m_thread.GetID(), m_valid,
+ IsPlanComplete());
m_takedown_done = true;
m_stop_address = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
m_real_stop_info_sp = GetPrivateStopInfo ();
if (!m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state))
{
if (log)
- log->Printf("ThreadPlanCallFunction(%p): DoTakedown failed to restore register state", this);
+ log->Printf("ThreadPlanCallFunction(%p): DoTakedown failed to restore register state",
+ static_cast<void*>(this));
}
SetPlanComplete(success);
ClearBreakpoints();
@@ -238,7 +252,9 @@ ThreadPlanCallFunction::DoTakedown (bool success)
else
{
if (log)
- log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called as no-op for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", this, m_thread.GetID(), m_valid, IsPlanComplete());
+ log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called as no-op for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n",
+ static_cast<void*>(this), m_thread.GetID(), m_valid,
+ IsPlanComplete());
}
}
@@ -317,6 +333,14 @@ ThreadPlanCallFunction::DoPlanExplainsStop (Event *event_ptr)
if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop())
return true;
+ // One more quirk here. If this event was from Halt interrupting the target, then we should not consider
+ // ourselves complete. Return true to acknowledge the stop.
+ if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr))
+ {
+ if (log)
+ log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: The event is an Interrupt, returning true.");
+ return true;
+ }
// We control breakpoints separately from other "stop reasons." So first,
// check the case where we stopped for an internal breakpoint, in that case, continue on.
// If it is not an internal breakpoint, consult m_ignore_breakpoints.
@@ -425,17 +449,6 @@ ThreadPlanCallFunction::StopOthers ()
return m_stop_other_threads;
}
-void
-ThreadPlanCallFunction::SetStopOthers (bool new_value)
-{
- if (m_subplan_sp)
- {
- ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
- address_plan->SetStopOthers(new_value);
- }
- m_stop_other_threads = new_value;
-}
-
StateType
ThreadPlanCallFunction::GetPlanRunState ()
{
@@ -470,11 +483,12 @@ bool
ThreadPlanCallFunction::MischiefManaged ()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
-
+
if (IsPlanComplete())
{
if (log)
- log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.", this);
+ log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.",
+ static_cast<void*>(this));
ThreadPlan::MischiefManaged ();
return true;
@@ -547,6 +561,13 @@ ThreadPlanCallFunction::BreakpointsExplainStop()
return false;
}
+void
+ThreadPlanCallFunction::SetStopOthers (bool new_value)
+{
+ m_subplan_sp->SetStopOthers(new_value);
+}
+
+
bool
ThreadPlanCallFunction::RestoreThreadState()
{
diff --git a/source/Target/ThreadPlanCallUserExpression.cpp b/source/Target/ThreadPlanCallUserExpression.cpp
index 827de3e6057a..90b8cf81171f 100644
--- a/source/Target/ThreadPlanCallUserExpression.cpp
+++ b/source/Target/ThreadPlanCallUserExpression.cpp
@@ -12,7 +12,7 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
-#include "llvm/Support/MachO.h"
+
// Project includes
#include "lldb/lldb-private-log.h"
#include "lldb/Breakpoint/Breakpoint.h"
@@ -21,6 +21,7 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -56,7 +57,54 @@ ThreadPlanCallUserExpression::~ThreadPlanCallUserExpression ()
void
ThreadPlanCallUserExpression::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
- ThreadPlanCallFunction::GetDescription (s, level);
+ if (level == eDescriptionLevelBrief)
+ s->Printf("User Expression thread plan");
+ else
+ ThreadPlanCallFunction::GetDescription (s, level);
+}
+
+void
+ThreadPlanCallUserExpression::WillPop ()
+{
+ ThreadPlanCallFunction::WillPop();
+ if (m_user_expression_sp)
+ m_user_expression_sp.reset();
+}
+
+bool
+ThreadPlanCallUserExpression::MischiefManaged ()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+
+ if (IsPlanComplete())
+ {
+ if (log)
+ log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.",
+ static_cast<void*>(this));
+
+ if (m_manage_materialization && PlanSucceeded() && m_user_expression_sp)
+ {
+ lldb::addr_t function_stack_top;
+ lldb::addr_t function_stack_bottom;
+ lldb::addr_t function_stack_pointer = GetFunctionStackPointer();
+
+ function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
+ function_stack_top = function_stack_pointer;
+
+ StreamString error_stream;
+
+ ExecutionContext exe_ctx(GetThread());
+
+ m_user_expression_sp->FinalizeJITExecution(error_stream, exe_ctx, m_result_var_sp, function_stack_bottom, function_stack_top);
+ }
+
+ ThreadPlan::MischiefManaged ();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
StopInfoSP
diff --git a/source/Target/ThreadPlanRunToAddress.cpp b/source/Target/ThreadPlanRunToAddress.cpp
index 9e7713973054..e2f85c0c5f5f 100644
--- a/source/Target/ThreadPlanRunToAddress.cpp
+++ b/source/Target/ThreadPlanRunToAddress.cpp
@@ -69,7 +69,7 @@ ThreadPlanRunToAddress::ThreadPlanRunToAddress
m_addresses (addresses),
m_break_ids ()
{
- // Convert all addressses into opcode addresses to make sure we set
+ // Convert all addresses into opcode addresses to make sure we set
// breakpoints at the correct address.
Target &target = thread.GetProcess()->GetTarget();
std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
diff --git a/source/Target/ThreadPlanShouldStopHere.cpp b/source/Target/ThreadPlanShouldStopHere.cpp
index 87662345a06d..e89f5d2bde1b 100644
--- a/source/Target/ThreadPlanShouldStopHere.cpp
+++ b/source/Target/ThreadPlanShouldStopHere.cpp
@@ -23,12 +23,23 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// ThreadPlanShouldStopHere constructor
//----------------------------------------------------------------------
-ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner, ThreadPlanShouldStopHereCallback callback, void *baton) :
- m_callback (callback),
- m_baton (baton),
+ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner) :
+ m_callbacks (),
+ m_baton (NULL),
m_owner (owner),
m_flags (ThreadPlanShouldStopHere::eNone)
{
+ m_callbacks.should_stop_here_callback = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback;
+ m_callbacks.step_from_here_callback = ThreadPlanShouldStopHere::DefaultStepFromHereCallback;
+}
+
+ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner, const ThreadPlanShouldStopHereCallbacks *callbacks, void *baton) :
+ m_callbacks (),
+ m_baton (),
+ m_owner (owner),
+ m_flags (ThreadPlanShouldStopHere::eNone)
+{
+ SetShouldStopHereCallbacks(callbacks, baton);
}
//----------------------------------------------------------------------
@@ -38,37 +49,120 @@ ThreadPlanShouldStopHere::~ThreadPlanShouldStopHere()
{
}
-void
-ThreadPlanShouldStopHere::SetShouldStopHereCallback (ThreadPlanShouldStopHereCallback callback, void *baton)
+bool
+ThreadPlanShouldStopHere::InvokeShouldStopHereCallback (FrameComparison operation)
{
- m_callback = callback;
- m_baton = baton;
-}
-
-ThreadPlanSP
-ThreadPlanShouldStopHere::InvokeShouldStopHereCallback ()
-{
- if (m_callback)
+ bool should_stop_here = true;
+ if (m_callbacks.should_stop_here_callback)
{
- ThreadPlanSP return_plan_sp(m_callback (m_owner, m_flags, m_baton));
+ should_stop_here = m_callbacks.should_stop_here_callback (m_owner, m_flags, operation, m_baton);
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
{
lldb::addr_t current_addr = m_owner->GetThread().GetRegisterContext()->GetPC(0);
- if (return_plan_sp)
- {
- StreamString s;
- return_plan_sp->GetDescription (&s, lldb::eDescriptionLevelFull);
- log->Printf ("ShouldStopHere callback found a step out plan from 0x%" PRIx64 ": %s.", current_addr, s.GetData());
- }
- else
- {
- log->Printf ("ShouldStopHere callback didn't find a step out plan from: 0x%" PRIx64 ".", current_addr);
- }
+ log->Printf ("ShouldStopHere callback returned %u from 0x%" PRIx64 ".", should_stop_here, current_addr);
}
+ }
+
+ return should_stop_here;
+}
+
+bool
+ThreadPlanShouldStopHere::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
+ Flags &flags,
+ FrameComparison operation,
+ void *baton)
+{
+ bool should_stop_here = true;
+ StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
+ if (!frame)
+ return true;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+
+ if ((operation == eFrameCompareOlder && flags.Test(eStepOutAvoidNoDebug))
+ || (operation == eFrameCompareYounger && flags.Test(eStepInAvoidNoDebug))
+ || (operation == eFrameCompareSameParent && flags.Test(eStepInAvoidNoDebug)))
+ {
+ if (!frame->HasDebugInformation())
+ {
+ if (log)
+ log->Printf ("Stepping out of frame with no debug info");
+
+ should_stop_here = false;
+ }
+ }
+
+ // Always avoid code with line number 0.
+ // FIXME: At present the ShouldStop and the StepFromHere calculate this independently. If this ever
+ // becomes expensive (this one isn't) we can try to have this set a state that the StepFromHere can use.
+ if (frame)
+ {
+ SymbolContext sc;
+ sc = frame->GetSymbolContext (eSymbolContextLineEntry);
+ if (sc.line_entry.line == 0)
+ should_stop_here = false;
+ }
+
+ return should_stop_here;
+}
+
+ThreadPlanSP
+ThreadPlanShouldStopHere::DefaultStepFromHereCallback (ThreadPlan *current_plan,
+ Flags &flags,
+ FrameComparison operation,
+ void *baton)
+{
+ const bool stop_others = false;
+ const size_t frame_index = 0;
+ ThreadPlanSP return_plan_sp;
+ // If we are stepping through code at line number 0, then we need to step over this range. Otherwise
+ // we will step out.
+ StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
+ if (!frame)
return return_plan_sp;
+ SymbolContext sc;
+ sc = frame->GetSymbolContext (eSymbolContextLineEntry);
+ if (sc.line_entry.line == 0)
+ {
+ AddressRange range = sc.line_entry.range;
+ return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepOverRange(false,
+ range,
+ sc,
+ eOnlyDuringStepping,
+ eLazyBoolNo);
+ }
+
+ if (!return_plan_sp)
+ return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepOutNoShouldStop (false,
+ NULL,
+ true,
+ stop_others,
+ eVoteNo,
+ eVoteNoOpinion,
+ frame_index);
+ return return_plan_sp;
+}
+
+ThreadPlanSP
+ThreadPlanShouldStopHere::QueueStepOutFromHerePlan(lldb_private::Flags &flags, lldb::FrameComparison operation)
+{
+ ThreadPlanSP return_plan_sp;
+ if (m_callbacks.step_from_here_callback)
+ {
+ return_plan_sp = m_callbacks.step_from_here_callback (m_owner, flags, operation, m_baton);
}
+ return return_plan_sp;
+
+}
+
+lldb::ThreadPlanSP
+ThreadPlanShouldStopHere::CheckShouldStopHereAndQueueStepOut (lldb::FrameComparison operation)
+{
+ if (!InvokeShouldStopHereCallback(operation))
+ return QueueStepOutFromHerePlan(m_flags, operation);
else
return ThreadPlanSP();
}
+
diff --git a/source/Target/ThreadPlanStepInRange.cpp b/source/Target/ThreadPlanStepInRange.cpp
index c4cb9aba1b3e..3e9abef65573 100644
--- a/source/Target/ThreadPlanStepInRange.cpp
+++ b/source/Target/ThreadPlanStepInRange.cpp
@@ -31,7 +31,7 @@
using namespace lldb;
using namespace lldb_private;
-uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug;
+uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eStepInAvoidNoDebug;
//----------------------------------------------------------------------
// ThreadPlanStepInRange: Step through a stack range, either stepping over or into
@@ -43,14 +43,18 @@ ThreadPlanStepInRange::ThreadPlanStepInRange
Thread &thread,
const AddressRange &range,
const SymbolContext &addr_context,
- lldb::RunMode stop_others
+ lldb::RunMode stop_others,
+ LazyBool step_in_avoids_code_without_debug_info,
+ LazyBool step_out_avoids_code_without_debug_info
) :
ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
- ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
+ ThreadPlanShouldStopHere (this),
m_step_past_prologue (true),
m_virtual_step (false)
{
+ SetCallbacks();
SetFlagsToDefault ();
+ SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, step_out_avoids_code_without_debug_info);
}
ThreadPlanStepInRange::ThreadPlanStepInRange
@@ -59,15 +63,19 @@ ThreadPlanStepInRange::ThreadPlanStepInRange
const AddressRange &range,
const SymbolContext &addr_context,
const char *step_into_target,
- lldb::RunMode stop_others
+ lldb::RunMode stop_others,
+ LazyBool step_in_avoids_code_without_debug_info,
+ LazyBool step_out_avoids_code_without_debug_info
) :
ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
- ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
+ ThreadPlanShouldStopHere (this),
m_step_past_prologue (true),
m_virtual_step (false),
m_step_into_target (step_into_target)
{
+ SetCallbacks();
SetFlagsToDefault ();
+ SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, step_out_avoids_code_without_debug_info);
}
ThreadPlanStepInRange::~ThreadPlanStepInRange ()
@@ -75,6 +83,48 @@ ThreadPlanStepInRange::~ThreadPlanStepInRange ()
}
void
+ThreadPlanStepInRange::SetupAvoidNoDebug(LazyBool step_in_avoids_code_without_debug_info,
+ LazyBool step_out_avoids_code_without_debug_info)
+{
+ bool avoid_nodebug = true;
+
+ switch (step_in_avoids_code_without_debug_info)
+ {
+ case eLazyBoolYes:
+ avoid_nodebug = true;
+ break;
+ case eLazyBoolNo:
+ avoid_nodebug = false;
+ break;
+ case eLazyBoolCalculate:
+ avoid_nodebug = m_thread.GetStepInAvoidsNoDebug();
+ break;
+ }
+ if (avoid_nodebug)
+ GetFlags().Set (ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
+ else
+ GetFlags().Clear (ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
+
+ avoid_nodebug = true;
+ switch (step_out_avoids_code_without_debug_info)
+ {
+ case eLazyBoolYes:
+ avoid_nodebug = true;
+ break;
+ case eLazyBoolNo:
+ avoid_nodebug = false;
+ break;
+ case eLazyBoolCalculate:
+ avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
+ break;
+ }
+ if (avoid_nodebug)
+ GetFlags().Set (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+ else
+ GetFlags().Clear (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+}
+
+void
ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
if (level == lldb::eDescriptionLevelBrief)
@@ -124,7 +174,8 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
{
// If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise
// we're done.
- m_sub_plan_sp = InvokeShouldStopHereCallback();
+ // FIXME - This can be both a step in and a step out. Probably should record which in the m_virtual_step.
+ m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger);
}
else
{
@@ -139,7 +190,7 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
FrameComparison frame_order = CompareCurrentFrameToStartFrame();
- if (frame_order == eFrameCompareOlder)
+ if (frame_order == eFrameCompareOlder || frame_order == eFrameCompareSameParent)
{
// If we're in an older frame then we should stop.
//
@@ -148,7 +199,12 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
// in a trampoline we think the frame is older because the trampoline confused the backtracer.
m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
if (!m_sub_plan_sp)
- return true;
+ {
+ // Otherwise check the ShouldStopHere for step out:
+ m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
+ if (log)
+ log->Printf ("ShouldStopHere says we should step out of this frame.");
+ }
else if (log)
{
log->Printf("Thought I stepped out, but in fact arrived at a trampoline.");
@@ -196,7 +252,7 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
// If not, give the "should_stop" callback a chance to push a plan to get us out of here.
// But only do that if we actually have stepped in.
if (!m_sub_plan_sp && frame_order == eFrameCompareYounger)
- m_sub_plan_sp = InvokeShouldStopHereCallback();
+ m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
// If we've stepped in and we are going to stop here, check to see if we were asked to
// run past the prologue, and if so do that.
@@ -251,12 +307,6 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
}
}
-void
-ThreadPlanStepInRange::SetFlagsToDefault ()
-{
- GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values);
-}
-
void
ThreadPlanStepInRange::SetAvoidRegexp(const char *name)
{
@@ -344,25 +394,19 @@ ThreadPlanStepInRange::FrameMatchesAvoidCriteria ()
return false;
}
-ThreadPlanSP
-ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton)
+bool
+ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, FrameComparison operation, void *baton)
{
- bool should_step_out = false;
+ bool should_stop_here = true;
StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- if (flags.Test(eAvoidNoDebug))
- {
- if (!frame->HasDebugInformation())
- {
- if (log)
- log->Printf ("Stepping out of frame with no debug info");
-
- should_step_out = true;
- }
- }
+ // First see if the ThreadPlanShouldStopHere default implementation thinks we should get out of here:
+ should_stop_here = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback (current_plan, flags, operation, baton);
+ if (!should_stop_here)
+ return should_stop_here;
- if (current_plan->GetKind() == eKindStepInRange)
+ if (should_stop_here && current_plan->GetKind() == eKindStepInRange && operation == eFrameCompareYounger)
{
ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
if (step_in_range_plan->m_step_into_target)
@@ -373,7 +417,7 @@ ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
// First try an exact match, since that's cheap with ConstStrings. Then do a strstr compare.
if (step_in_range_plan->m_step_into_target == sc.GetFunctionName())
{
- should_step_out = false;
+ should_stop_here = true;
}
else
{
@@ -381,42 +425,26 @@ ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
const char *function_name = sc.GetFunctionName().AsCString();
if (function_name == NULL)
- should_step_out = true;
+ should_stop_here = false;
else if (strstr (function_name, target_name) == NULL)
- should_step_out = true;
+ should_stop_here = false;
}
- if (log && should_step_out)
+ if (log && !should_stop_here)
log->Printf("Stepping out of frame %s which did not match step into target %s.",
sc.GetFunctionName().AsCString(),
step_in_range_plan->m_step_into_target.AsCString());
}
}
- if (!should_step_out)
+ if (should_stop_here)
{
ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
// Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidCriteria.
- should_step_out = step_in_range_plan->FrameMatchesAvoidCriteria ();
+ should_stop_here = !step_in_range_plan->FrameMatchesAvoidCriteria ();
}
}
-
- if (should_step_out)
- {
- // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
- // We really should have all plans take the tri-state for "stop others" so we can do the right
- // thing. For now let's be safe and always run others when we are likely to run arbitrary code.
- const bool stop_others = false;
- return current_plan->GetThread().QueueThreadPlanForStepOut (false,
- NULL,
- true,
- stop_others,
- eVoteNo,
- eVoteNoOpinion,
- 0); // Frame index
- }
-
- return ThreadPlanSP();
+ return should_stop_here;
}
bool
diff --git a/source/Target/ThreadPlanStepInstruction.cpp b/source/Target/ThreadPlanStepInstruction.cpp
index f644ee88f701..fabf63b1e9d6 100644
--- a/source/Target/ThreadPlanStepInstruction.cpp
+++ b/source/Target/ThreadPlanStepInstruction.cpp
@@ -43,21 +43,28 @@ ThreadPlanStepInstruction::ThreadPlanStepInstruction
m_stop_other_threads (stop_other_threads),
m_step_over (step_over)
{
+ m_takes_iteration_count = true;
+ SetUpState();
+}
+
+ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
+{
+}
+
+void
+ThreadPlanStepInstruction::SetUpState()
+{
m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0);
- StackFrameSP m_start_frame_sp(m_thread.GetStackFrameAtIndex(0));
- m_stack_id = m_start_frame_sp->GetStackID();
+ StackFrameSP start_frame_sp(m_thread.GetStackFrameAtIndex(0));
+ m_stack_id = start_frame_sp->GetStackID();
- m_start_has_symbol = m_start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != NULL;
+ m_start_has_symbol = start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != NULL;
StackFrameSP parent_frame_sp = m_thread.GetStackFrameAtIndex(1);
if (parent_frame_sp)
m_parent_frame_id = parent_frame_sp->GetStackID();
}
-ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
-{
-}
-
void
ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
@@ -106,6 +113,37 @@ ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr)
}
bool
+ThreadPlanStepInstruction::IsPlanStale ()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+ StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
+ if (cur_frame_id == m_stack_id)
+ {
+ if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
+ return true;
+ else
+ return false;
+ }
+ else if (cur_frame_id < m_stack_id)
+ {
+ // If the current frame is younger than the start frame and we are stepping over, then we need to continue,
+ // but if we are doing just one step, we're done.
+ if (m_step_over)
+ return false;
+ else
+ return true;
+ }
+ else
+ {
+ if (log)
+ {
+ log->Printf ("ThreadPlanStepInstruction::IsPlanStale - Current frame is older than start frame, plan is stale.");
+ }
+ return true;
+ }
+}
+
+bool
ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
{
if (m_step_over)
@@ -118,8 +156,18 @@ ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
{
if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
{
- SetPlanComplete();
- return true;
+ if (--m_iteration_count <= 0)
+ {
+ SetPlanComplete();
+ return true;
+ }
+ else
+ {
+ // We are still stepping, reset the start pc, and in case we've stepped out,
+ // reset the current stack id.
+ SetUpState();
+ return false;
+ }
}
else
return false;
@@ -147,13 +195,13 @@ ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
// StepInstruction should probably have the tri-state RunMode, but for now it is safer to
// run others.
const bool stop_others = false;
- m_thread.QueueThreadPlanForStepOut(false,
- NULL,
- true,
- stop_others,
- eVoteNo,
- eVoteNoOpinion,
- 0);
+ m_thread.QueueThreadPlanForStepOutNoShouldStop(false,
+ NULL,
+ true,
+ stop_others,
+ eVoteNo,
+ eVoteNoOpinion,
+ 0);
return false;
}
else
@@ -182,8 +230,18 @@ ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
{
if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
{
- SetPlanComplete();
- return true;
+ if (--m_iteration_count <= 0)
+ {
+ SetPlanComplete();
+ return true;
+ }
+ else
+ {
+ // We are still stepping, reset the start pc, and in case we've stepped in or out,
+ // reset the current stack id.
+ SetUpState();
+ return false;
+ }
}
else
return false;
diff --git a/source/Target/ThreadPlanStepOut.cpp b/source/Target/ThreadPlanStepOut.cpp
index c5efb5581527..b62f557319a8 100644
--- a/source/Target/ThreadPlanStepOut.cpp
+++ b/source/Target/ThreadPlanStepOut.cpp
@@ -26,10 +26,13 @@
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlanStepOverRange.h"
+#include "lldb/Target/ThreadPlanStepThrough.h"
using namespace lldb;
using namespace lldb_private;
+uint32_t ThreadPlanStepOut::s_default_flag_values = 0;
+
//----------------------------------------------------------------------
// ThreadPlanStepOut: Step out of the current frame
//----------------------------------------------------------------------
@@ -41,20 +44,21 @@ ThreadPlanStepOut::ThreadPlanStepOut
bool stop_others,
Vote stop_vote,
Vote run_vote,
- uint32_t frame_idx
+ uint32_t frame_idx,
+ LazyBool step_out_avoids_code_without_debug_info
) :
ThreadPlan (ThreadPlan::eKindStepOut, "Step out", thread, stop_vote, run_vote),
- m_step_from_context (context),
+ ThreadPlanShouldStopHere (this),
m_step_from_insn (LLDB_INVALID_ADDRESS),
m_return_bp_id (LLDB_INVALID_BREAK_ID),
m_return_addr (LLDB_INVALID_ADDRESS),
- m_first_insn (first_insn),
m_stop_others (stop_others),
- m_step_through_inline_plan_sp(),
- m_step_out_plan_sp (),
m_immediate_step_from_function(NULL)
{
+ SetFlagsToDefault();
+ SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
+
m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
StackFrameSP return_frame_sp (m_thread.GetStackFrameAtIndex(frame_idx + 1));
@@ -77,13 +81,15 @@ ThreadPlanStepOut::ThreadPlanStepOut
{
// First queue a plan that gets us to this inlined frame, and when we get there we'll queue a second
// plan that walks us out of this frame.
- m_step_out_plan_sp.reset (new ThreadPlanStepOut(m_thread,
+ m_step_out_to_inline_plan_sp.reset (new ThreadPlanStepOut(m_thread,
NULL,
false,
stop_others,
eVoteNoOpinion,
eVoteNoOpinion,
- frame_idx - 1));
+ frame_idx - 1,
+ eLazyBoolNo));
+ static_cast<ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get())->SetShouldStopHereCallbacks(nullptr, nullptr);
}
else
{
@@ -123,10 +129,32 @@ ThreadPlanStepOut::ThreadPlanStepOut
}
void
+ThreadPlanStepOut::SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info)
+{
+ bool avoid_nodebug = true;
+ switch (step_out_avoids_code_without_debug_info)
+ {
+ case eLazyBoolYes:
+ avoid_nodebug = true;
+ break;
+ case eLazyBoolNo:
+ avoid_nodebug = false;
+ break;
+ case eLazyBoolCalculate:
+ avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
+ break;
+ }
+ if (avoid_nodebug)
+ GetFlags().Set (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+ else
+ GetFlags().Clear (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+}
+
+void
ThreadPlanStepOut::DidPush()
{
- if (m_step_out_plan_sp)
- m_thread.QueueThreadPlan(m_step_out_plan_sp, false);
+ if (m_step_out_to_inline_plan_sp)
+ m_thread.QueueThreadPlan(m_step_out_to_inline_plan_sp, false);
else if (m_step_through_inline_plan_sp)
m_thread.QueueThreadPlan(m_step_through_inline_plan_sp, false);
}
@@ -144,7 +172,7 @@ ThreadPlanStepOut::GetDescription (Stream *s, lldb::DescriptionLevel level)
s->Printf ("step out");
else
{
- if (m_step_out_plan_sp)
+ if (m_step_out_to_inline_plan_sp)
s->Printf ("Stepping out to inlined frame so we can walk through it.");
else if (m_step_through_inline_plan_sp)
s->Printf ("Stepping out by stepping through inlined function.");
@@ -159,8 +187,8 @@ ThreadPlanStepOut::GetDescription (Stream *s, lldb::DescriptionLevel level)
bool
ThreadPlanStepOut::ValidatePlan (Stream *error)
{
- if (m_step_out_plan_sp)
- return m_step_out_plan_sp->ValidatePlan (error);
+ if (m_step_out_to_inline_plan_sp)
+ return m_step_out_to_inline_plan_sp->ValidatePlan (error);
else if (m_step_through_inline_plan_sp)
return m_step_through_inline_plan_sp->ValidatePlan (error);
else if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
@@ -176,12 +204,18 @@ ThreadPlanStepOut::ValidatePlan (Stream *error)
bool
ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
{
- // If one of our child plans just finished, then we do explain the stop.
- if (m_step_out_plan_sp)
+ // If the step out plan is done, then we just need to step through the inlined frame.
+ if (m_step_out_to_inline_plan_sp)
{
- if (m_step_out_plan_sp->MischiefManaged())
+ if (m_step_out_to_inline_plan_sp->MischiefManaged())
+ return true;
+ else
+ return false;
+ }
+ else if (m_step_through_inline_plan_sp)
+ {
+ if (m_step_through_inline_plan_sp->MischiefManaged())
{
- // If this one is done, then we are all done.
CalculateReturnValue();
SetPlanComplete();
return true;
@@ -189,9 +223,9 @@ ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
else
return false;
}
- else if (m_step_through_inline_plan_sp)
+ else if (m_step_out_further_plan_sp)
{
- if (m_step_through_inline_plan_sp->MischiefManaged())
+ if (m_step_out_further_plan_sp->MischiefManaged())
return true;
else
return false;
@@ -234,8 +268,11 @@ ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
if (done)
{
- CalculateReturnValue();
- SetPlanComplete();
+ if (InvokeShouldStopHereCallback (eFrameCompareOlder))
+ {
+ CalculateReturnValue();
+ SetPlanComplete();
+ }
}
// If there was only one owner, then we're done. But if we also hit some
@@ -266,61 +303,70 @@ ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
bool
ThreadPlanStepOut::ShouldStop (Event *event_ptr)
{
- if (IsPlanComplete())
- return true;
-
- bool done;
-
+ if (IsPlanComplete())
+ return true;
+
+ bool done = false;
+ if (m_step_out_to_inline_plan_sp)
+ {
+ if (m_step_out_to_inline_plan_sp->MischiefManaged())
+ {
+ // Now step through the inlined stack we are in:
+ if (QueueInlinedStepPlan(true))
+ {
+ // If we can't queue a plan to do this, then just call ourselves done.
+ m_step_out_to_inline_plan_sp.reset();
+ SetPlanComplete (false);
+ return true;
+ }
+ else
+ done = true;
+ }
+ else
+ return m_step_out_to_inline_plan_sp->ShouldStop(event_ptr);
+ }
+ else if (m_step_through_inline_plan_sp)
+ {
+ if (m_step_through_inline_plan_sp->MischiefManaged())
+ done = true;
+ else
+ return m_step_through_inline_plan_sp->ShouldStop(event_ptr);
+ }
+ else if (m_step_out_further_plan_sp)
+ {
+ if (m_step_out_further_plan_sp->MischiefManaged())
+ m_step_out_further_plan_sp.reset();
+ else
+ return m_step_out_further_plan_sp->ShouldStop(event_ptr);
+ }
+
+ if (!done)
+ {
StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
if (frame_zero_id < m_step_out_to_id)
done = false;
else
done = true;
-
- if (done)
+ }
+
+ // The normal step out computations think we are done, so all we need to do is consult the ShouldStopHere,
+ // and we are done.
+
+ if (done)
+ {
+ if (InvokeShouldStopHereCallback(eFrameCompareOlder))
{
CalculateReturnValue();
SetPlanComplete();
- return true;
}
else
{
- if (m_step_out_plan_sp)
- {
- if (m_step_out_plan_sp->MischiefManaged())
- {
- // Now step through the inlined stack we are in:
- if (QueueInlinedStepPlan(true))
- {
- return false;
- }
- else
- {
- CalculateReturnValue();
- SetPlanComplete ();
- return true;
- }
- }
- else
- return m_step_out_plan_sp->ShouldStop(event_ptr);
- }
- else if (m_step_through_inline_plan_sp)
- {
- if (m_step_through_inline_plan_sp->MischiefManaged())
- {
- // We don't calculate the return value here because we don't know how to.
- // But in case we had a return value sitting around from our process in
- // getting here, let's clear it out.
- m_return_valobj_sp.reset();
- SetPlanComplete();
- return true;
- }
- else
- return m_step_through_inline_plan_sp->ShouldStop(event_ptr);
- }
- else
- return false;
+ m_step_out_further_plan_sp = QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder);
+ done = false;
}
+ }
+
+ return done;
}
bool
@@ -338,7 +384,7 @@ ThreadPlanStepOut::GetPlanRunState ()
bool
ThreadPlanStepOut::DoWillResume (StateType resume_state, bool current_plan)
{
- if (m_step_out_plan_sp || m_step_through_inline_plan_sp)
+ if (m_step_out_to_inline_plan_sp || m_step_through_inline_plan_sp)
return true;
if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
@@ -427,10 +473,12 @@ ThreadPlanStepOut::QueueInlinedStepPlan (bool queue_now)
inlined_block->CalculateSymbolContext(&inlined_sc);
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);
+ run_mode,
+ avoid_no_debug);
step_through_inline_plan_ptr->SetOkayToDiscard(true);
StreamString errors;
if (!step_through_inline_plan_ptr->ValidatePlan(&errors))
@@ -486,4 +534,3 @@ ThreadPlanStepOut::IsPlanStale()
else
return true;
}
-
diff --git a/source/Target/ThreadPlanStepOverRange.cpp b/source/Target/ThreadPlanStepOverRange.cpp
index 2d8108bf9b77..a4f3743346e2 100644
--- a/source/Target/ThreadPlanStepOverRange.cpp
+++ b/source/Target/ThreadPlanStepOverRange.cpp
@@ -31,6 +31,7 @@
using namespace lldb_private;
using namespace lldb;
+uint32_t ThreadPlanStepOverRange::s_default_flag_values = 0;
//----------------------------------------------------------------------
// ThreadPlanStepOverRange: Step through a stack range, either stepping over or into
@@ -42,11 +43,15 @@ ThreadPlanStepOverRange::ThreadPlanStepOverRange
Thread &thread,
const AddressRange &range,
const SymbolContext &addr_context,
- lldb::RunMode stop_others
+ lldb::RunMode stop_others,
+ LazyBool step_out_avoids_code_without_debug_info
) :
ThreadPlanStepRange (ThreadPlan::eKindStepOverRange, "Step range stepping over", thread, range, addr_context, stop_others),
+ ThreadPlanShouldStopHere (this),
m_first_resume(true)
{
+ SetFlagsToDefault();
+ SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
}
ThreadPlanStepOverRange::~ThreadPlanStepOverRange ()
@@ -65,6 +70,32 @@ ThreadPlanStepOverRange::GetDescription (Stream *s, lldb::DescriptionLevel level
}
}
+void
+ThreadPlanStepOverRange::SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info)
+{
+ bool avoid_nodebug = true;
+ switch (step_out_avoids_code_without_debug_info)
+ {
+ case eLazyBoolYes:
+ avoid_nodebug = true;
+ break;
+ case eLazyBoolNo:
+ avoid_nodebug = false;
+ break;
+ case eLazyBoolCalculate:
+ avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
+ break;
+ }
+ if (avoid_nodebug)
+ GetFlags().Set (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+ else
+ GetFlags().Clear (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+ // Step Over plans should always avoid no-debug on step in. Seems like you shouldn't
+ // have to say this, but a tail call looks more like a step in that a step out, so
+ // we want to catch this case.
+ GetFlags().Set (ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
+}
+
bool
ThreadPlanStepOverRange::IsEquivalentContext(const SymbolContext &context)
{
@@ -146,18 +177,21 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
const SymbolContext &older_context = older_frame_sp->GetSymbolContext(eSymbolContextEverything);
if (IsEquivalentContext(older_context))
{
- new_plan_sp = m_thread.QueueThreadPlanForStepOut (false,
- NULL,
- true,
- stop_others,
- eVoteNo,
- eVoteNoOpinion,
- 0);
+ new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop (false,
+ NULL,
+ true,
+ stop_others,
+ eVoteNo,
+ eVoteNoOpinion,
+ 0);
break;
}
else
{
new_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
+ // If we found a way through, then we should stop recursing.
+ if (new_plan_sp)
+ break;
}
}
}
@@ -277,6 +311,13 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
// If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it:
ClearNextBranchBreakpoint();
+
+ // If we haven't figured out something to do yet, then ask the ShouldStopHere callback:
+ if (!new_plan_sp)
+ {
+ new_plan_sp = CheckShouldStopHereAndQueueStepOut (frame_order);
+ }
+
if (!new_plan_sp)
m_no_more_plans = true;
else
@@ -390,3 +431,4 @@ ThreadPlanStepOverRange::DoWillResume (lldb::StateType resume_state, bool curren
return true;
}
+
diff --git a/source/Target/ThreadPlanStepRange.cpp b/source/Target/ThreadPlanStepRange.cpp
index 309f773c505b..82ca59fbca39 100644
--- a/source/Target/ThreadPlanStepRange.cpp
+++ b/source/Target/ThreadPlanStepRange.cpp
@@ -50,6 +50,7 @@ ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind,
m_address_ranges (),
m_stop_others (stop_others),
m_stack_id (),
+ m_parent_stack_id(),
m_no_more_plans (false),
m_first_run_event (true),
m_use_fast_step(false)
@@ -57,6 +58,9 @@ ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind,
m_use_fast_step = GetTarget().GetUseFastStepping();
AddRange(range);
m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
+ StackFrameSP parent_stack = m_thread.GetStackFrameAtIndex(1);
+ if (parent_stack)
+ m_parent_stack_id = parent_stack->GetStackID();
}
ThreadPlanStepRange::~ThreadPlanStepRange ()
@@ -270,7 +274,16 @@ ThreadPlanStepRange::CompareCurrentFrameToStartFrame()
}
else
{
- frame_order = eFrameCompareOlder;
+ StackFrameSP cur_parent_frame = m_thread.GetStackFrameAtIndex(1);
+ StackID cur_parent_id;
+ if (cur_parent_frame)
+ cur_parent_id = cur_parent_frame->GetStackID();
+ if (m_parent_stack_id.IsValid()
+ && cur_parent_id.IsValid()
+ && m_parent_stack_id == cur_parent_id)
+ frame_order = eFrameCompareSameParent;
+ else
+ frame_order = eFrameCompareOlder;
}
return frame_order;
}
@@ -443,8 +456,8 @@ ThreadPlanStepRange::NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info
}
}
if (log)
- log->Printf ("ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit next range breakpoint which has %zu owners - explains stop: %u.",
- num_owners,
+ log->Printf ("ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit next range breakpoint which has %" PRIu64 " owners - explains stop: %u.",
+ (uint64_t)num_owners,
explains_stop);
ClearNextBranchBreakpoint();
return explains_stop;
diff --git a/source/Target/ThreadPlanStepUntil.cpp b/source/Target/ThreadPlanStepUntil.cpp
index 62e05c7fe342..fa5ab8c5d491 100644
--- a/source/Target/ThreadPlanStepUntil.cpp
+++ b/source/Target/ThreadPlanStepUntil.cpp
@@ -77,7 +77,7 @@ ThreadPlanStepUntil::ThreadPlanStepUntil
}
}
- m_stack_id = m_thread.GetStackFrameAtIndex(frame_idx)->GetStackID();
+ m_stack_id = frame_sp->GetStackID();
// Now set breakpoints on all our return addresses:
for (size_t i = 0; i < num_addresses; i++)
diff --git a/source/Target/ThreadPlanTracer.cpp b/source/Target/ThreadPlanTracer.cpp
index d191170fcc08..5188df6d9193 100644
--- a/source/Target/ThreadPlanTracer.cpp
+++ b/source/Target/ThreadPlanTracer.cpp
@@ -166,17 +166,6 @@ ThreadPlanAssemblyTracer::TracingEnded ()
m_register_values.clear();
}
-static void
-PadOutTo (StreamString &stream, int target)
-{
- stream.Flush();
-
- int length = stream.GetString().length();
-
- if (length + 1 < target)
- stream.Printf("%*s", target - (length + 1) + 1, "");
-}
-
void
ThreadPlanAssemblyTracer::Log ()
{
diff --git a/source/Utility/ARM64_DWARF_Registers.cpp b/source/Utility/ARM64_DWARF_Registers.cpp
new file mode 100644
index 000000000000..d9b386319434
--- /dev/null
+++ b/source/Utility/ARM64_DWARF_Registers.cpp
@@ -0,0 +1,148 @@
+//===-- ARM64_DWARF_Registers.c ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "ARM64_DWARF_Registers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace arm64_dwarf;
+
+const char *
+arm64_dwarf::GetRegisterName (unsigned reg_num, bool altnernate_name)
+{
+ if (altnernate_name)
+ {
+ switch (reg_num)
+ {
+ case fp: return "x29";
+ case lr: return "x30";
+ case sp: return "x31";
+ default:
+ break;
+ }
+ return nullptr;
+ }
+
+ switch (reg_num)
+ {
+ case x0: return "x0";
+ case x1: return "x1";
+ case x2: return "x2";
+ case x3: return "x3";
+ case x4: return "x4";
+ case x5: return "x5";
+ case x6: return "x6";
+ case x7: return "x7";
+ case x8: return "x8";
+ case x9: return "x9";
+ case x10: return "x10";
+ case x11: return "x11";
+ case x12: return "x12";
+ case x13: return "x13";
+ case x14: return "x14";
+ case x15: return "x15";
+ case x16: return "x16";
+ case x17: return "x17";
+ case x18: return "x18";
+ case x19: return "x19";
+ case x20: return "x20";
+ case x21: return "x21";
+ case x22: return "x22";
+ case x23: return "x23";
+ case x24: return "x24";
+ case x25: return "x25";
+ case x26: return "x26";
+ case x27: return "x27";
+ case x28: return "x28";
+ case fp: return "fp";
+ case lr: return "lr";
+ case sp: return "sp";
+ case pc: return "pc";
+ case cpsr: return "cpsr";
+ case v0: return "v0";
+ case v1: return "v1";
+ case v2: return "v2";
+ case v3: return "v3";
+ case v4: return "v4";
+ case v5: return "v5";
+ case v6: return "v6";
+ case v7: return "v7";
+ case v8: return "v8";
+ case v9: return "v9";
+ case v10: return "v10";
+ case v11: return "v11";
+ case v12: return "v12";
+ case v13: return "v13";
+ case v14: return "v14";
+ case v15: return "v15";
+ case v16: return "v16";
+ case v17: return "v17";
+ case v18: return "v18";
+ case v19: return "v19";
+ case v20: return "v20";
+ case v21: return "v21";
+ case v22: return "v22";
+ case v23: return "v23";
+ case v24: return "v24";
+ case v25: return "v25";
+ case v26: return "v26";
+ case v27: return "v27";
+ case v28: return "v28";
+ case v29: return "v29";
+ case v30: return "v30";
+ case v31: return "v31";
+ }
+ return nullptr;
+}
+
+bool
+arm64_dwarf::GetRegisterInfo (unsigned reg_num, RegisterInfo &reg_info)
+{
+ ::memset (&reg_info, 0, sizeof(RegisterInfo));
+ ::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
+
+ if (reg_num >= x0 && reg_num <= pc)
+ {
+ reg_info.byte_size = 8;
+ reg_info.format = eFormatHex;
+ reg_info.encoding = eEncodingUint;
+ }
+ else if (reg_num >= v0 && reg_num <= v31)
+ {
+ reg_info.byte_size = 16;
+ reg_info.format = eFormatVectorOfFloat32;
+ reg_info.encoding = eEncodingVector;
+ }
+ else if (reg_num == cpsr)
+ {
+ reg_info.byte_size = 4;
+ reg_info.format = eFormatHex;
+ reg_info.encoding = eEncodingUint;
+ }
+ else
+ {
+ return false;
+ }
+
+ reg_info.name = arm64_dwarf::GetRegisterName (reg_num, false);
+ reg_info.alt_name = arm64_dwarf::GetRegisterName (reg_num, true);
+ reg_info.kinds[eRegisterKindDWARF] = reg_num;
+
+ switch (reg_num)
+ {
+ case fp: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break;
+ case lr: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break;
+ case sp: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break;
+ case pc: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break;
+ default: break;
+ }
+ return true;
+}
diff --git a/source/Utility/ARM64_DWARF_Registers.h b/source/Utility/ARM64_DWARF_Registers.h
new file mode 100644
index 000000000000..832f25d45b5d
--- /dev/null
+++ b/source/Utility/ARM64_DWARF_Registers.h
@@ -0,0 +1,102 @@
+//===-- ARM64_DWARF_Registers.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_ARM64_DWARF_Registers_h_
+#define utility_ARM64_DWARF_Registers_h_
+
+#include "lldb/lldb-private.h"
+
+namespace arm64_dwarf {
+
+enum
+{
+ x0 = 0,
+ x1,
+ x2,
+ x3,
+ x4,
+ x5,
+ x6,
+ x7,
+ x8,
+ x9,
+ x10,
+ x11,
+ x12,
+ x13,
+ x14,
+ x15,
+ x16,
+ x17,
+ x18,
+ x19,
+ x20,
+ x21,
+ x22,
+ x23,
+ x24,
+ x25,
+ x26,
+ x27,
+ x28,
+ x29 = 29, fp = x29,
+ x30 = 30, lr = x30,
+ x31 = 31, sp = x31,
+ pc = 32,
+ cpsr = 33,
+ // 34-63 reserved
+
+ // V0-V31 (128 bit vector registers)
+ v0 = 64,
+ v1,
+ v2,
+ v3,
+ v4,
+ v5,
+ v6,
+ v7,
+ v8,
+ v9,
+ v10,
+ v11,
+ v12,
+ v13,
+ v14,
+ v15,
+ v16,
+ v17,
+ v18,
+ v19,
+ v20,
+ v21,
+ v22,
+ v23,
+ v24,
+ v25,
+ v26,
+ v27,
+ v28,
+ v29,
+ v30,
+ v31
+
+ // 96-127 reserved
+};
+
+const char *
+GetRegisterName (unsigned reg_num, bool altnernate_name);
+
+bool
+GetRegisterInfo (unsigned reg_num,
+ lldb_private::RegisterInfo &reg_info);
+
+} // namespace arm64_dwarf
+
+#endif // utility_ARM64_DWARF_Registers_h_
+
diff --git a/source/Utility/ARM64_GCC_Registers.h b/source/Utility/ARM64_GCC_Registers.h
new file mode 100644
index 000000000000..2166b3bf591a
--- /dev/null
+++ b/source/Utility/ARM64_GCC_Registers.h
@@ -0,0 +1,92 @@
+//===-- ARM64_gdb_Registers.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_ARM64_gdb_Registers_h_
+#define utility_ARM64_gdb_Registers_h_
+
+namespace arm64_gcc {
+
+enum
+{
+ x0 = 0,
+ x1,
+ x2,
+ x3,
+ x4,
+ x5,
+ x6,
+ x7,
+ x8,
+ x9,
+ x10,
+ x11,
+ x12,
+ x13,
+ x14,
+ x15,
+ x16,
+ x17,
+ x18,
+ x19,
+ x20,
+ x21,
+ x22,
+ x23,
+ x24,
+ x25,
+ x26,
+ x27,
+ x28,
+ fp, // aka x29
+ lr, // aka x30
+ sp, // aka x31 aka wzr
+ pc, // value is 32
+ cpsr
+};
+
+enum
+{
+ v0 = 64,
+ v1,
+ v2,
+ v3,
+ v4,
+ v5,
+ v6,
+ v7,
+ v8,
+ v9,
+ v10,
+ v11,
+ v12,
+ v13,
+ v14,
+ v15,
+ v16,
+ v17,
+ v18,
+ v19,
+ v20,
+ v21,
+ v22,
+ v23,
+ v24,
+ v25,
+ v26,
+ v27,
+ v28,
+ v29,
+ v30,
+ v31 // 95
+};
+
+}
+
+#endif // utility_ARM64_gdb_Registers_h_
+
diff --git a/source/Utility/ARM_DWARF_Registers.cpp b/source/Utility/ARM_DWARF_Registers.cpp
index 491ba040863e..64472ba1a79e 100644
--- a/source/Utility/ARM_DWARF_Registers.cpp
+++ b/source/Utility/ARM_DWARF_Registers.cpp
@@ -202,7 +202,7 @@ GetARMDWARFRegisterName (unsigned reg_num)
case dwarf_q14: return "q14";
case dwarf_q15: return "q15";
}
- return 0;
+ return nullptr;
}
bool
diff --git a/source/Utility/PseudoTerminal.cpp b/source/Utility/PseudoTerminal.cpp
index 98d581def4c3..c906ea273005 100644
--- a/source/Utility/PseudoTerminal.cpp
+++ b/source/Utility/PseudoTerminal.cpp
@@ -19,6 +19,7 @@
#ifdef _WIN32
#include "lldb/Host/windows/win32.h"
+typedef uint32_t pid_t;
// empty functions
int posix_openpt(int flag) { return 0; }
@@ -47,7 +48,7 @@ PseudoTerminal::PseudoTerminal () :
// Destructor
//
// The destructor will close the master and slave file descriptors
-// if they are valid and ownwership has not been released using the
+// if they are valid and ownership has not been released using the
// ReleaseMasterFileDescriptor() or the ReleaseSaveFileDescriptor()
// member functions.
//----------------------------------------------------------------------
@@ -155,7 +156,7 @@ PseudoTerminal::OpenSlave (int oflag, char *error_str, size_t error_len)
// Open the master side of a pseudo terminal
const char *slave_name = GetSlaveName (error_str, error_len);
- if (slave_name == NULL)
+ if (slave_name == nullptr)
return false;
m_slave_fd = ::open (slave_name, oflag);
@@ -193,11 +194,11 @@ PseudoTerminal::GetSlaveName (char *error_str, size_t error_len) const
{
if (error_str)
::snprintf (error_str, error_len, "%s", "master file descriptor is invalid");
- return NULL;
+ return nullptr;
}
const char *slave_name = ::ptsname (m_master_fd);
- if (error_str && slave_name == NULL)
+ if (error_str && slave_name == nullptr)
::strerror_r (errno, error_str, error_len);
return slave_name;
diff --git a/source/Utility/SharingPtr.cpp b/source/Utility/SharingPtr.cpp
index be237cec61c4..4083975bba7c 100644
--- a/source/Utility/SharingPtr.cpp
+++ b/source/Utility/SharingPtr.cpp
@@ -18,6 +18,8 @@
#include <assert.h>
#include "lldb/Host/Mutex.h"
+#include "llvm/ADT/STLExtras.h"
+
#include <vector>
class Backtrace
@@ -51,7 +53,7 @@ void
Backtrace::GetFrames ()
{
void *frames[1024];
- const int count = ::backtrace (frames, sizeof(frames)/sizeof(void*));
+ const int count = ::backtrace (frames, llvm::array_lengthof(frames));
if (count > 2)
m_frames.assign (frames + 2, frames + (count - 2));
}
diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp
index 9d2315708821..8747853213cb 100644
--- a/source/Utility/StringExtractor.cpp
+++ b/source/Utility/StringExtractor.cpp
@@ -63,16 +63,6 @@ xdigit_to_sint (char ch)
return ch - '0';
}
-static inline unsigned int
-xdigit_to_uint (uint8_t ch)
-{
- if (ch >= 'a' && ch <= 'f')
- return 10u + ch - 'a';
- if (ch >= 'A' && ch <= 'F')
- return 10u + ch - 'A';
- return ch - '0';
-}
-
//----------------------------------------------------------------------
// StringExtractor constructor
//----------------------------------------------------------------------
@@ -165,7 +155,7 @@ StringExtractor::GetU32 (uint32_t fail_value, int base)
{
if (m_index < m_packet.size())
{
- char *end = NULL;
+ char *end = nullptr;
const char *start = m_packet.c_str();
const char *cstr = start + m_index;
uint32_t result = ::strtoul (cstr, &end, base);
@@ -184,7 +174,7 @@ StringExtractor::GetS32 (int32_t fail_value, int base)
{
if (m_index < m_packet.size())
{
- char *end = NULL;
+ char *end = nullptr;
const char *start = m_packet.c_str();
const char *cstr = start + m_index;
int32_t result = ::strtol (cstr, &end, base);
@@ -204,7 +194,7 @@ StringExtractor::GetU64 (uint64_t fail_value, int base)
{
if (m_index < m_packet.size())
{
- char *end = NULL;
+ char *end = nullptr;
const char *start = m_packet.c_str();
const char *cstr = start + m_index;
uint64_t result = ::strtoull (cstr, &end, base);
@@ -223,7 +213,7 @@ StringExtractor::GetS64 (int64_t fail_value, int base)
{
if (m_index < m_packet.size())
{
- char *end = NULL;
+ char *end = nullptr;
const char *start = m_packet.c_str();
const char *cstr = start + m_index;
int64_t result = ::strtoll (cstr, &end, base);
@@ -429,6 +419,18 @@ StringExtractor::GetHexByteString (std::string &str)
}
size_t
+StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
+{
+ str.clear();
+
+ uint32_t nibble_count = 0;
+ for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2)
+ {}
+
+ return str.size();
+}
+
+size_t
StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
char terminator)
{
@@ -438,6 +440,7 @@ StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
str.append(1, ch);
if (Peek() && *Peek() == terminator)
return str.size();
+
str.clear();
return str.size();
}
diff --git a/source/Utility/StringExtractor.h b/source/Utility/StringExtractor.h
index 2aab3b09f47e..697499309ced 100644
--- a/source/Utility/StringExtractor.h
+++ b/source/Utility/StringExtractor.h
@@ -129,6 +129,9 @@ public:
GetHexByteString (std::string &str);
size_t
+ GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length);
+
+ size_t
GetHexByteStringTerminatedBy (std::string &str,
char terminator);
@@ -137,7 +140,7 @@ public:
{
if (m_index < m_packet.size())
return m_packet.c_str() + m_index;
- return NULL;
+ return nullptr;
}
protected:
diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp
index eccb81318131..17717dbe6e20 100644
--- a/source/Utility/StringExtractorGDBRemote.cpp
+++ b/source/Utility/StringExtractorGDBRemote.cpp
@@ -92,6 +92,7 @@ StringExtractorGDBRemote::GetServerPacketType () const
if (PACKET_MATCHES ("QStartNoAckMode")) return eServerPacketType_QStartNoAckMode;
if (PACKET_STARTS_WITH ("QSaveRegisterState")) return eServerPacketType_QSaveRegisterState;
if (PACKET_STARTS_WITH ("QSetDisableASLR:")) return eServerPacketType_QSetDisableASLR;
+ if (PACKET_STARTS_WITH ("QSetDetachOnError:")) return eServerPacketType_QSetDetachOnError;
if (PACKET_STARTS_WITH ("QSetSTDIN:")) return eServerPacketType_QSetSTDIN;
if (PACKET_STARTS_WITH ("QSetSTDOUT:")) return eServerPacketType_QSetSTDOUT;
if (PACKET_STARTS_WITH ("QSetSTDERR:")) return eServerPacketType_QSetSTDERR;
@@ -178,6 +179,7 @@ StringExtractorGDBRemote::GetServerPacketType () const
if (PACKET_STARTS_WITH ("qSpeedTest:")) return eServerPacketType_qSpeedTest;
if (PACKET_MATCHES ("qShlibInfoAddr")) return eServerPacketType_qShlibInfoAddr;
if (PACKET_MATCHES ("qStepPacketSupported")) return eServerPacketType_qStepPacketSupported;
+ if (PACKET_STARTS_WITH ("qSupported")) return eServerPacketType_qSupported;
if (PACKET_MATCHES ("qSyncThreadStateSupported")) return eServerPacketType_qSyncThreadStateSupported;
break;
@@ -198,6 +200,10 @@ StringExtractorGDBRemote::GetServerPacketType () const
if (PACKET_STARTS_WITH ("qWatchpointSupportInfo:")) return eServerPacketType_qWatchpointSupportInfo;
if (PACKET_MATCHES ("qWatchpointSupportInfo")) return eServerPacketType_qWatchpointSupportInfoSupported;
break;
+
+ case 'X':
+ if (PACKET_STARTS_WITH ("qXfer:auxv:read::")) return eServerPacketType_qXfer_auxv_read;
+ break;
}
break;
case 'v':
diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h
index f8af3ca41a79..e16403c2d154 100644
--- a/source/Utility/StringExtractorGDBRemote.h
+++ b/source/Utility/StringExtractorGDBRemote.h
@@ -62,6 +62,7 @@ public:
eServerPacketType_QEnvironment,
eServerPacketType_QLaunchArch,
eServerPacketType_QSetDisableASLR,
+ eServerPacketType_QSetDetachOnError,
eServerPacketType_QSetSTDIN,
eServerPacketType_QSetSTDOUT,
eServerPacketType_QSetSTDERR,
@@ -105,12 +106,14 @@ public:
eServerPacketType_qRegisterInfo,
eServerPacketType_qShlibInfoAddr,
eServerPacketType_qStepPacketSupported,
+ eServerPacketType_qSupported,
eServerPacketType_qSyncThreadStateSupported,
eServerPacketType_qThreadExtraInfo,
eServerPacketType_qThreadStopInfo,
eServerPacketType_qVAttachOrWaitSupported,
eServerPacketType_qWatchpointSupportInfo,
eServerPacketType_qWatchpointSupportInfoSupported,
+ eServerPacketType_qXfer_auxv_read,
eServerPacketType_vAttach,
eServerPacketType_vAttachWait,
diff --git a/source/Utility/StringLexer.cpp b/source/Utility/StringLexer.cpp
new file mode 100644
index 000000000000..bde2fc6a4202
--- /dev/null
+++ b/source/Utility/StringLexer.cpp
@@ -0,0 +1,101 @@
+//===--------------------- StringLexer.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/StringLexer.h"
+
+#include <algorithm>
+
+using namespace lldb_utility;
+
+StringLexer::StringLexer (std::string s) :
+m_data(s),
+m_position(0),
+m_putback_data()
+{ }
+
+StringLexer::StringLexer (const StringLexer& rhs) :
+m_data(rhs.m_data),
+m_position(rhs.m_position),
+m_putback_data(rhs.m_putback_data)
+{ }
+
+StringLexer::Character
+StringLexer::Peek ()
+{
+ if (m_putback_data.empty())
+ return m_data[m_position];
+ else
+ return m_putback_data.front();
+}
+
+bool
+StringLexer::NextIf (Character c)
+{
+ auto val = Peek();
+ if (val == c)
+ {
+ Next();
+ return true;
+ }
+ return false;
+}
+
+StringLexer::Character
+StringLexer::Next ()
+{
+ auto val = Peek();
+ Consume();
+ return val;
+}
+
+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);
+}
+
+
+void
+StringLexer::PutBack (Character c)
+{
+ m_putback_data.push_back(c);
+}
+
+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;
+}
+
+void
+StringLexer::Consume()
+{
+ if (m_putback_data.empty())
+ m_position++;
+ else
+ m_putback_data.pop_front();
+}
+
+StringLexer&
+StringLexer::operator = (const StringLexer& rhs)
+{
+ if (this != &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/TimeSpecTimeout.h b/source/Utility/TimeSpecTimeout.h
index 32cdd067658c..388ccc179c17 100644
--- a/source/Utility/TimeSpecTimeout.h
+++ b/source/Utility/TimeSpecTimeout.h
@@ -76,7 +76,7 @@ public:
GetTimeSpecPtr () const
{
if (m_infinite)
- return NULL;
+ return nullptr;
return &m_timespec;
}
diff --git a/source/lldb-log.cpp b/source/lldb-log.cpp
index 12ec3a546e1b..4311c1ad084f 100644
--- a/source/lldb-log.cpp
+++ b/source/lldb-log.cpp
@@ -145,6 +145,7 @@ lldb_private::DisableLog (const char **categories, Stream *feedback_strm)
else if (0 == ::strncasecmp(arg, "module", 6)) flag_bits &= ~LIBLLDB_LOG_MODULES;
else if (0 == ::strncasecmp(arg, "mmap", 4)) flag_bits &= ~LIBLLDB_LOG_MMAP;
else if (0 == ::strcasecmp(arg, "os")) flag_bits &= ~LIBLLDB_LOG_OS;
+ else if (0 == ::strcasecmp(arg, "jit")) flag_bits &= ~LIBLLDB_LOG_JIT_LOADER;
else
{
feedback_strm->Printf ("error: unrecognized log category '%s'\n", arg);
@@ -220,6 +221,7 @@ lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const ch
else if (0 == ::strncasecmp(arg, "unwind", 6)) flag_bits |= LIBLLDB_LOG_UNWIND;
else if (0 == ::strcasecmp(arg, "verbose")) flag_bits |= LIBLLDB_LOG_VERBOSE;
else if (0 == ::strncasecmp(arg, "watch", 5)) flag_bits |= LIBLLDB_LOG_WATCHPOINTS;
+ else if (0 == ::strcasecmp(arg, "jit")) flag_bits |= LIBLLDB_LOG_JIT_LOADER;
else
{
feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
@@ -251,8 +253,9 @@ lldb_private::ListLogCategories (Stream *strm)
" events - log broadcaster, listener and event queue activities\n"
" expr - log expressions\n"
" host - log host activities\n"
+ " jit - log JIT events in the target\n"
" mmap - log mmap related activities\n"
- " module - log module activities such as when modules are created, detroyed, replaced, and more\n"
+ " module - log module activities such as when modules are created, destroyed, replaced, and more\n"
" object - log object construction/destruction for important objects\n"
" os - log OperatingSystem plugin related activities\n"
" platform - log platform events and activities\n"
diff --git a/source/lldb.cpp b/source/lldb.cpp
index 4817e7f2b44c..cd620b7945b9 100644
--- a/source/lldb.cpp
+++ b/source/lldb.cpp
@@ -18,34 +18,43 @@
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Timer.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Interpreter/ScriptInterpreterPython.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/TargetSelect.h"
#include "Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h"
#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/Disassembler/llvm/DisassemblerLLVMC.h"
+#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
+#include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h"
#include "Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h"
-#include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h"
+#include "Plugins/JITLoader/GDB/JITLoaderGDB.h"
+#include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h"
#include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h"
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
-#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
-#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h"
-#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
-#include "Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h"
-#include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"
#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
-#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
#include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h"
#include "Plugins/Platform/Linux/PlatformLinux.h"
#include "Plugins/Platform/POSIX/PlatformPOSIX.h"
#include "Plugins/Platform/Windows/PlatformWindows.h"
-#include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h"
+#include "Plugins/Platform/Kalimba/PlatformKalimba.h"
+#include "Plugins/Process/elf-core/ProcessElfCore.h"
+#include "Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h"
+#include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h"
+#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
+#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h"
+#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
+#include "Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h"
+#include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"
+
#ifndef LLDB_DISABLE_PYTHON
#include "Plugins/OperatingSystem/Python/OperatingSystemPython.h"
#endif
@@ -66,14 +75,15 @@
#include "Plugins/Process/mach-core/ProcessMachCore.h"
-#if defined(__linux__) || defined(__FreeBSD__)
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
-#endif
#if defined (__linux__)
#include "Plugins/Process/Linux/ProcessLinux.h"
#endif
+#if defined (_WIN32)
+#include "Plugins/Process/Windows/ProcessWindows.h"
+#endif
+
#if defined (__FreeBSD__)
#include "Plugins/Process/POSIX/ProcessPOSIX.h"
#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h"
@@ -86,6 +96,12 @@
using namespace lldb;
using namespace lldb_private;
+static void fatal_error_handler(void *user_data, const std::string& reason,
+ bool gen_crash_diag) {
+ Host::SetCrashDescription(reason.c_str());
+ ::abort();
+}
+
void
lldb_private::Initialize ()
{
@@ -98,11 +114,21 @@ lldb_private::Initialize ()
{
g_inited = true;
Log::Initialize();
+ HostInfo::Initialize();
Timer::Initialize ();
Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
-
+
+ // Initialize LLVM and Clang
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllDisassemblers();
+ llvm::install_fatal_error_handler(fatal_error_handler, 0);
+
+ // Initialize plug-ins
ABIMacOSX_i386::Initialize();
ABIMacOSX_arm::Initialize();
+ ABIMacOSX_arm64::Initialize();
ABISysV_x86_64::Initialize();
DisassemblerLLVMC::Initialize();
ObjectContainerBSDArchive::Initialize();
@@ -113,18 +139,22 @@ lldb_private::Initialize ()
UnwindAssemblyInstEmulation::Initialize();
UnwindAssembly_x86::Initialize();
EmulateInstructionARM::Initialize ();
+ EmulateInstructionARM64::Initialize ();
ObjectFilePECOFF::Initialize ();
DynamicLoaderPOSIXDYLD::Initialize ();
PlatformFreeBSD::Initialize();
PlatformLinux::Initialize();
PlatformWindows::Initialize();
+ PlatformKalimba::Initialize();
SymbolFileDWARFDebugMap::Initialize();
ItaniumABILanguageRuntime::Initialize();
#ifndef LLDB_DISABLE_PYTHON
ScriptInterpreterPython::InitializePrivate();
OperatingSystemPython::Initialize();
#endif
-
+ JITLoaderGDB::Initialize();
+ ProcessElfCore::Initialize();
+
#if defined (__APPLE__)
//----------------------------------------------------------------------
// Apple/Darwin hosted plugins
@@ -150,13 +180,13 @@ lldb_private::Initialize ()
//----------------------------------------------------------------------
ProcessLinux::Initialize();
#endif
+#if defined(_WIN32)
+ ProcessWindows::Initialize();
+#endif
#if defined (__FreeBSD__)
ProcessFreeBSD::Initialize();
#endif
-#if defined(__linux__) || defined(__FreeBSD__)
- ProcessElfCore::Initialize();
-#endif
//----------------------------------------------------------------------
// Platform agnostic plugins
//----------------------------------------------------------------------
@@ -189,6 +219,7 @@ lldb_private::Terminate ()
PluginManager::Terminate();
ABIMacOSX_i386::Terminate();
ABIMacOSX_arm::Terminate();
+ ABIMacOSX_arm64::Terminate();
ABISysV_x86_64::Terminate();
DisassemblerLLVMC::Terminate();
ObjectContainerBSDArchive::Terminate();
@@ -199,17 +230,21 @@ lldb_private::Terminate ()
UnwindAssembly_x86::Terminate();
UnwindAssemblyInstEmulation::Terminate();
EmulateInstructionARM::Terminate ();
+ EmulateInstructionARM64::Terminate ();
ObjectFilePECOFF::Terminate ();
DynamicLoaderPOSIXDYLD::Terminate ();
PlatformFreeBSD::Terminate();
PlatformLinux::Terminate();
PlatformWindows::Terminate();
+ PlatformKalimba::Terminate();
SymbolFileDWARFDebugMap::Terminate();
ItaniumABILanguageRuntime::Terminate();
#ifndef LLDB_DISABLE_PYTHON
OperatingSystemPython::Terminate();
#endif
-
+ JITLoaderGDB::Terminate();
+ ProcessElfCore::Terminate();
+
#if defined (__APPLE__)
DynamicLoaderMacOSXDYLD::Terminate();
DynamicLoaderDarwinKernel::Terminate();
@@ -237,9 +272,6 @@ lldb_private::Terminate ()
ProcessFreeBSD::Terminate();
#endif
-#if defined(__linux__) || defined(__FreeBSD__)
- ProcessElfCore::Terminate();
-#endif
ProcessGDBRemote::Terminate();
DynamicLoaderStatic::Terminate();
@@ -292,7 +324,8 @@ lldb_private::GetVersion ()
size_t version_len = sizeof(g_version_string);
- if (newline_loc && (newline_loc - version_string < version_len))
+ if (newline_loc &&
+ (newline_loc - version_string < static_cast<ptrdiff_t>(version_len)))
version_len = newline_loc - version_string;
::strncpy(g_version_string, version_string, version_len);