aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2013-11-06 16:48:53 +0000
committerEd Maste <emaste@FreeBSD.org>2013-11-06 16:48:53 +0000
commitf21a844f60ae6c74fcf1fddca32461acce3c1ee0 (patch)
tree56d79f94966870db1cecd65a7264510a25fd1cba
parent37d22554be9f5a677dad2a95b7ef22fe59c66a8a (diff)
downloadsrc-f21a844f60ae6c74fcf1fddca32461acce3c1ee0.tar.gz
src-f21a844f60ae6c74fcf1fddca32461acce3c1ee0.zip
Import lldb as of SVN r194122vendor/lldb/lldb-r194122
Sponsored by: DARPA, AFRL
Notes
Notes: svn path=/vendor/lldb/dist/; revision=257752 svn path=/vendor/lldb/lldb-r194122/; revision=257753; tag=vendor/lldb/lldb-r194122
-rw-r--r--include/lldb/API/SBHostOS.h4
-rw-r--r--include/lldb/API/SBProcess.h32
-rw-r--r--include/lldb/API/SBTarget.h3
-rw-r--r--include/lldb/API/SBThread.h9
-rw-r--r--include/lldb/Breakpoint/Breakpoint.h14
-rw-r--r--include/lldb/Breakpoint/BreakpointList.h10
-rw-r--r--include/lldb/Breakpoint/BreakpointLocation.h5
-rw-r--r--include/lldb/Breakpoint/BreakpointResolver.h7
-rw-r--r--include/lldb/Breakpoint/BreakpointSiteList.h1
-rw-r--r--include/lldb/Breakpoint/StoppointLocation.h14
-rw-r--r--include/lldb/Core/Address.h12
-rw-r--r--include/lldb/Core/ArchSpec.h4
-rw-r--r--include/lldb/Core/ConnectionFileDescriptor.h27
-rw-r--r--include/lldb/Core/ConnectionMachPort.h3
-rw-r--r--include/lldb/Core/ConstString.h6
-rw-r--r--include/lldb/Core/DataExtractor.h21
-rw-r--r--include/lldb/Core/Debugger.h4
-rw-r--r--include/lldb/Core/Disassembler.h3
-rw-r--r--include/lldb/Core/EmulateInstruction.h6
-rw-r--r--include/lldb/Core/Error.h11
-rw-r--r--include/lldb/Core/Flags.h1
-rw-r--r--include/lldb/Core/Log.h3
-rw-r--r--include/lldb/Core/Module.h69
-rw-r--r--include/lldb/Core/ModuleList.h30
-rw-r--r--include/lldb/Core/ModuleSpec.h2
-rw-r--r--include/lldb/Core/Opcode.h15
-rw-r--r--include/lldb/Core/PluginManager.h18
-rw-r--r--include/lldb/Core/RangeMap.h61
-rw-r--r--include/lldb/Core/RegularExpression.h29
-rw-r--r--include/lldb/Core/StreamGDBRemote.h54
-rw-r--r--include/lldb/Core/UUID.h2
-rw-r--r--include/lldb/Core/Value.h2
-rw-r--r--include/lldb/Core/ValueObject.h269
-rw-r--r--include/lldb/Core/ValueObjectDynamicValue.h4
-rw-r--r--include/lldb/Core/dwarf.h1
-rw-r--r--include/lldb/DataFormatters/CXXFormatterFunctions.h33
-rw-r--r--include/lldb/DataFormatters/DataVisualization.h43
-rw-r--r--include/lldb/DataFormatters/FormatCache.h20
-rw-r--r--include/lldb/DataFormatters/FormatClasses.h18
-rw-r--r--include/lldb/DataFormatters/FormatManager.h29
-rw-r--r--include/lldb/DataFormatters/FormatNavigator.h2
-rw-r--r--include/lldb/DataFormatters/TypeCategory.h49
-rw-r--r--include/lldb/DataFormatters/TypeCategoryMap.h4
-rw-r--r--include/lldb/DataFormatters/TypeSummary.h5
-rw-r--r--include/lldb/DataFormatters/TypeSynthetic.h14
-rw-r--r--include/lldb/DataFormatters/ValueObjectPrinter.h394
-rw-r--r--include/lldb/Expression/ClangExpressionDeclMap.h14
-rw-r--r--include/lldb/Expression/ClangFunction.h65
-rw-r--r--include/lldb/Expression/ClangUserExpression.h83
-rw-r--r--include/lldb/Expression/DWARFExpression.h21
-rw-r--r--include/lldb/Expression/IRExecutionUnit.h11
-rw-r--r--include/lldb/Expression/IRForTarget.h1
-rw-r--r--include/lldb/Host/Condition.h6
-rw-r--r--include/lldb/Host/Config.h6
-rw-r--r--include/lldb/Host/File.h55
-rw-r--r--include/lldb/Host/FileSpec.h17
-rw-r--r--include/lldb/Host/Host.h56
-rw-r--r--include/lldb/Host/Mutex.h6
-rw-r--r--include/lldb/Host/OptionParser.h53
-rw-r--r--include/lldb/Host/ProcessRunLock.h81
-rw-r--r--include/lldb/Host/SocketAddress.h9
-rw-r--r--include/lldb/Host/Symbols.h1
-rw-r--r--include/lldb/Host/Terminal.h3
-rw-r--r--include/lldb/Host/TimeValue.h24
-rw-r--r--include/lldb/Interpreter/Args.h5
-rw-r--r--include/lldb/Interpreter/CommandObject.h2
-rw-r--r--include/lldb/Interpreter/OptionGroupValueObjectDisplay.h4
-rw-r--r--include/lldb/Interpreter/OptionValueBoolean.h2
-rw-r--r--include/lldb/Interpreter/OptionValueEnumeration.h2
-rw-r--r--include/lldb/Interpreter/Options.h15
-rw-r--r--include/lldb/Interpreter/PythonDataObjects.h2
-rw-r--r--include/lldb/Interpreter/ScriptInterpreter.h124
-rw-r--r--include/lldb/Interpreter/ScriptInterpreterPython.h40
-rw-r--r--include/lldb/Symbol/Block.h1
-rw-r--r--include/lldb/Symbol/ClangASTImporter.h2
-rw-r--r--include/lldb/Symbol/ClangASTType.h13
-rw-r--r--include/lldb/Symbol/ClangNamespaceDecl.h4
-rw-r--r--include/lldb/Symbol/ObjectFile.h96
-rw-r--r--include/lldb/Symbol/Symbol.h33
-rw-r--r--include/lldb/Symbol/SymbolContext.h1
-rw-r--r--include/lldb/Symbol/Symtab.h4
-rw-r--r--include/lldb/Symbol/Type.h356
-rw-r--r--include/lldb/Symbol/TypeList.h1
-rw-r--r--include/lldb/Target/DynamicLoader.h20
-rw-r--r--include/lldb/Target/ExecutionContext.h3
-rw-r--r--include/lldb/Target/Platform.h363
-rw-r--r--include/lldb/Target/Process.h40
-rw-r--r--include/lldb/Target/RegisterContext.h5
-rw-r--r--include/lldb/Target/StackFrame.h368
-rw-r--r--include/lldb/Target/StackFrameList.h3
-rw-r--r--include/lldb/Target/StackID.h7
-rw-r--r--include/lldb/Target/SystemRuntime.h174
-rw-r--r--include/lldb/Target/Target.h92
-rw-r--r--include/lldb/Target/Thread.h38
-rw-r--r--include/lldb/Target/ThreadPlanCallFunction.h8
-rw-r--r--include/lldb/Target/ThreadPlanStepOverRange.h2
-rw-r--r--include/lldb/Utility/RefCounter.h56
-rw-r--r--include/lldb/Utility/SharingPtr.h41
-rw-r--r--include/lldb/lldb-defines.h12
-rw-r--r--include/lldb/lldb-enumerations.h7
-rw-r--r--include/lldb/lldb-forward.h10
-rw-r--r--include/lldb/lldb-private-enumerations.h13
-rw-r--r--include/lldb/lldb-private-interfaces.h1
-rw-r--r--include/lldb/lldb-private-log.h1
-rw-r--r--include/lldb/lldb-private.h4
-rw-r--r--include/lldb/lldb-types.h43
-rw-r--r--include/lldb/lldb-versioning.h2
-rw-r--r--source/API/SBCommandInterpreter.cpp125
-rw-r--r--source/API/SBData.cpp26
-rw-r--r--source/API/SBDebugger.cpp4
-rw-r--r--source/API/SBFileSpec.cpp2
-rw-r--r--source/API/SBFunction.cpp4
-rw-r--r--source/API/SBHostOS.cpp4
-rw-r--r--source/API/SBModuleSpec.cpp2
-rw-r--r--source/API/SBProcess.cpp40
-rw-r--r--source/API/SBSymbol.cpp4
-rw-r--r--source/API/SBTarget.cpp134
-rw-r--r--source/API/SBThread.cpp89
-rw-r--r--source/API/SBType.cpp84
-rw-r--r--source/API/SBTypeCategory.cpp41
-rw-r--r--source/API/SBTypeNameSpecifier.cpp2
-rw-r--r--source/API/SBValue.cpp174
-rw-r--r--source/Breakpoint/Breakpoint.cpp5
-rw-r--r--source/Breakpoint/BreakpointList.cpp4
-rw-r--r--source/Breakpoint/BreakpointLocation.cpp17
-rw-r--r--source/Breakpoint/BreakpointLocationList.cpp2
-rw-r--r--source/Breakpoint/BreakpointResolver.cpp144
-rw-r--r--source/Breakpoint/BreakpointResolverFileLine.cpp144
-rw-r--r--source/Breakpoint/BreakpointResolverFileRegex.cpp55
-rw-r--r--source/Breakpoint/BreakpointResolverName.cpp12
-rw-r--r--source/Breakpoint/StoppointLocation.cpp8
-rw-r--r--source/Commands/CommandCompletions.cpp128
-rw-r--r--source/Commands/CommandObjectArgs.cpp2
-rw-r--r--source/Commands/CommandObjectBreakpoint.cpp131
-rw-r--r--source/Commands/CommandObjectBreakpointCommand.cpp8
-rw-r--r--source/Commands/CommandObjectCommands.cpp30
-rw-r--r--source/Commands/CommandObjectDisassemble.cpp34
-rw-r--r--source/Commands/CommandObjectExpression.cpp50
-rw-r--r--source/Commands/CommandObjectExpression.h2
-rw-r--r--source/Commands/CommandObjectFrame.cpp26
-rw-r--r--source/Commands/CommandObjectHelp.cpp4
-rw-r--r--source/Commands/CommandObjectLog.cpp18
-rw-r--r--source/Commands/CommandObjectMemory.cpp65
-rw-r--r--source/Commands/CommandObjectPlatform.cpp1455
-rw-r--r--source/Commands/CommandObjectProcess.cpp42
-rw-r--r--source/Commands/CommandObjectRegister.cpp10
-rw-r--r--source/Commands/CommandObjectSettings.cpp2
-rw-r--r--source/Commands/CommandObjectSource.cpp20
-rw-r--r--source/Commands/CommandObjectTarget.cpp183
-rw-r--r--source/Commands/CommandObjectThread.cpp250
-rw-r--r--source/Commands/CommandObjectType.cpp466
-rw-r--r--source/Commands/CommandObjectWatchpoint.cpp22
-rw-r--r--source/Commands/CommandObjectWatchpointCommand.cpp8
-rw-r--r--source/Core/Address.cpp58
-rw-r--r--source/Core/ArchSpec.cpp143
-rw-r--r--source/Core/Communication.cpp4
-rw-r--r--source/Core/ConnectionFileDescriptor.cpp155
-rw-r--r--source/Core/ConnectionMachPort.cpp1
-rw-r--r--source/Core/ConnectionSharedMemory.cpp21
-rw-r--r--source/Core/ConstString.cpp6
-rw-r--r--source/Core/DataBufferMemoryMap.cpp67
-rw-r--r--source/Core/DataExtractor.cpp74
-rw-r--r--source/Core/Debugger.cpp30
-rw-r--r--source/Core/Disassembler.cpp8
-rw-r--r--source/Core/Error.cpp17
-rw-r--r--source/Core/FileLineResolver.cpp2
-rw-r--r--source/Core/Log.cpp6
-rw-r--r--source/Core/Mangled.cpp4693
-rw-r--r--source/Core/Module.cpp126
-rw-r--r--source/Core/ModuleList.cpp14
-rw-r--r--source/Core/Opcode.cpp22
-rw-r--r--source/Core/PluginManager.cpp105
-rw-r--r--source/Core/SearchFilter.cpp4
-rw-r--r--source/Core/SourceManager.cpp6
-rw-r--r--source/Core/StreamGDBRemote.cpp54
-rw-r--r--source/Core/Timer.cpp12
-rw-r--r--source/Core/Value.cpp32
-rw-r--r--source/Core/ValueObject.cpp442
-rw-r--r--source/Core/ValueObjectDynamicValue.cpp122
-rw-r--r--source/Core/ValueObjectSyntheticFilter.cpp6
-rw-r--r--source/Core/ValueObjectVariable.cpp4
-rw-r--r--source/DataFormatters/CXXFormatterFunctions.cpp8
-rw-r--r--source/DataFormatters/DataVisualization.cpp57
-rw-r--r--source/DataFormatters/FormatCache.cpp64
-rw-r--r--source/DataFormatters/FormatManager.cpp264
-rw-r--r--source/DataFormatters/LibCxxUnorderedMap.cpp135
-rw-r--r--source/DataFormatters/TypeCategory.cpp119
-rw-r--r--source/DataFormatters/TypeCategoryMap.cpp26
-rw-r--r--source/DataFormatters/TypeFormat.cpp2
-rw-r--r--source/DataFormatters/TypeSummary.cpp56
-rw-r--r--source/DataFormatters/ValueObjectPrinter.cpp623
-rw-r--r--source/Expression/ClangASTSource.cpp47
-rw-r--r--source/Expression/ClangExpressionDeclMap.cpp143
-rw-r--r--source/Expression/ClangExpressionParser.cpp9
-rw-r--r--source/Expression/ClangFunction.cpp15
-rw-r--r--source/Expression/ClangUserExpression.cpp96
-rw-r--r--source/Expression/DWARFExpression.cpp88
-rw-r--r--source/Expression/IRExecutionUnit.cpp8
-rw-r--r--source/Expression/IRForTarget.cpp8
-rw-r--r--source/Expression/IRInterpreter.cpp50
-rw-r--r--source/Expression/IRMemoryMap.cpp6
-rw-r--r--source/Expression/Materializer.cpp14
-rw-r--r--source/Host/common/Condition.cpp27
-rw-r--r--source/Host/common/File.cpp126
-rw-r--r--source/Host/common/FileSpec.cpp246
-rw-r--r--source/Host/common/Host.cpp599
-rw-r--r--source/Host/common/Mutex.cpp26
-rw-r--r--source/Host/common/OptionParser.cpp61
-rw-r--r--source/Host/common/ProcessRunLock.cpp71
-rw-r--r--source/Host/common/SocketAddress.cpp3
-rw-r--r--source/Host/common/Terminal.cpp21
-rw-r--r--source/Host/common/TimeValue.cpp36
-rw-r--r--source/Host/freebsd/Host.cpp139
-rw-r--r--source/Interpreter/Args.cpp136
-rw-r--r--source/Interpreter/CommandInterpreter.cpp43
-rw-r--r--source/Interpreter/CommandObject.cpp5
-rw-r--r--source/Interpreter/OptionGroupArchitecture.cpp2
-rw-r--r--source/Interpreter/OptionGroupBoolean.cpp4
-rw-r--r--source/Interpreter/OptionGroupFile.cpp4
-rw-r--r--source/Interpreter/OptionGroupFormat.cpp12
-rw-r--r--source/Interpreter/OptionGroupOutputFile.cpp4
-rw-r--r--source/Interpreter/OptionGroupPlatform.cpp8
-rw-r--r--source/Interpreter/OptionGroupString.cpp2
-rw-r--r--source/Interpreter/OptionGroupUInt64.cpp2
-rw-r--r--source/Interpreter/OptionGroupUUID.cpp2
-rw-r--r--source/Interpreter/OptionGroupValueObjectDisplay.cpp31
-rw-r--r--source/Interpreter/OptionGroupVariable.cpp16
-rw-r--r--source/Interpreter/OptionGroupWatchpoint.cpp4
-rw-r--r--source/Interpreter/OptionValueFileSpec.cpp26
-rw-r--r--source/Interpreter/OptionValueProperties.cpp1
-rw-r--r--source/Interpreter/Options.cpp28
-rw-r--r--source/Interpreter/PythonDataObjects.cpp60
-rw-r--r--source/Interpreter/ScriptInterpreter.cpp42
-rw-r--r--source/Interpreter/ScriptInterpreterPython.cpp232
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp47
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp58
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h24
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp157
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h6
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp36
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp4
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp115
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h36
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp159
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h24
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp2
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.h6
-rw-r--r--source/Plugins/Instruction/ARM/EmulationStateARM.h2
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp2
-rw-r--r--source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp19
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp85
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.h5
-rw-r--r--source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp2
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp61
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h8
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp541
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.h111
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp113
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h52
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp44
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.h3
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp196
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h27
-rw-r--r--source/Plugins/Process/POSIX/POSIXThread.cpp156
-rw-r--r--source/Plugins/Process/POSIX/POSIXThread.h16
-rw-r--r--source/Plugins/Process/POSIX/ProcessMessage.cpp6
-rw-r--r--source/Plugins/Process/POSIX/ProcessMessage.h14
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIX.cpp103
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIX.h8
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp78
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h29
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp90
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h29
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp129
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h15
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp96
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextLinux_i386.h29
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp151
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h15
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIX.h50
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp318
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h95
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp634
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h95
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp238
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h138
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp666
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h462
-rw-r--r--source/Plugins/Process/POSIX/RegisterContext_i386.cpp551
-rw-r--r--source/Plugins/Process/POSIX/RegisterContext_i386.h169
-rw-r--r--source/Plugins/Process/POSIX/RegisterContext_mips64.h104
-rw-r--r--source/Plugins/Process/POSIX/RegisterContext_x86.h541
-rw-r--r--source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp1563
-rw-r--r--source/Plugins/Process/POSIX/RegisterContext_x86_64.h347
-rw-r--r--source/Plugins/Process/POSIX/RegisterInfos_i386.h207
-rw-r--r--source/Plugins/Process/POSIX/RegisterInfos_mips64.h74
-rw-r--r--source/Plugins/Process/POSIX/RegisterInfos_x86_64.h409
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.cpp456
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.h17
-rw-r--r--source/Plugins/Process/Utility/InferiorCallPOSIX.cpp11
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp69
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp4
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.cpp16
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp18
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.cpp68
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.h47
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.cpp68
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.h54
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp94
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h58
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp92
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h58
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.cpp25
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp41
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp497
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h70
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp623
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h75
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp6
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h156
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp219
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h10
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp37
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.h3
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAttribute.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp32
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h3
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp30
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h43
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp41
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp42
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp39
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h23
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp10
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDefines.h1
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp12
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.h15
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp8
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFLocationList.h8
-rw-r--r--source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h10
-rw-r--r--source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp9
-rw-r--r--source/Plugins/SymbolFile/DWARF/NameToDIE.cpp1
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp150
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h64
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp2
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp4
-rw-r--r--source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp19
-rw-r--r--source/Symbol/ClangASTImporter.cpp15
-rw-r--r--source/Symbol/ClangASTType.cpp122
-rw-r--r--source/Symbol/CompileUnit.cpp2
-rw-r--r--source/Symbol/DWARFCallFrameInfo.cpp9
-rw-r--r--source/Symbol/FuncUnwinders.cpp23
-rw-r--r--source/Symbol/LineEntry.cpp6
-rw-r--r--source/Symbol/ObjectFile.cpp6
-rw-r--r--source/Symbol/Symbol.cpp120
-rw-r--r--source/Symbol/SymbolContext.cpp12
-rw-r--r--source/Symbol/Symtab.cpp11
-rw-r--r--source/Symbol/Type.cpp286
-rw-r--r--source/Symbol/UnwindTable.cpp2
-rw-r--r--source/Symbol/Variable.cpp11
-rw-r--r--source/Target/ExecutionContext.cpp10
-rw-r--r--source/Target/LanguageRuntime.cpp4
-rw-r--r--source/Target/Platform.cpp273
-rw-r--r--source/Target/Process.cpp176
-rw-r--r--source/Target/RegisterContext.cpp22
-rw-r--r--source/Target/StackFrame.cpp60
-rw-r--r--source/Target/StackFrameList.cpp34
-rw-r--r--source/Target/StopInfo.cpp23
-rw-r--r--source/Target/SystemRuntime.cpp73
-rw-r--r--source/Target/Target.cpp106
-rw-r--r--source/Target/TargetList.cpp2
-rw-r--r--source/Target/Thread.cpp118
-rw-r--r--source/Target/ThreadPlanRunToAddress.cpp2
-rw-r--r--source/Target/ThreadPlanStepOut.cpp2
-rw-r--r--source/Target/ThreadPlanStepOverRange.cpp76
-rw-r--r--source/Target/ThreadPlanStepRange.cpp25
-rw-r--r--source/Target/ThreadPlanStepThrough.cpp2
-rw-r--r--source/Target/ThreadPlanStepUntil.cpp4
-rw-r--r--source/Target/UnixSignals.cpp4
-rw-r--r--source/Utility/PseudoTerminal.cpp15
-rw-r--r--source/Utility/RefCounter.cpp25
-rw-r--r--source/Utility/SharingPtr.cpp12
-rw-r--r--source/Utility/StringExtractor.cpp78
-rw-r--r--source/Utility/StringExtractor.h13
-rw-r--r--source/Utility/StringExtractorGDBRemote.cpp45
-rw-r--r--source/Utility/StringExtractorGDBRemote.h19
-rw-r--r--source/lldb-log.cpp32
-rw-r--r--source/lldb.cpp13
-rw-r--r--tools/driver/Driver.cpp227
-rw-r--r--tools/driver/Driver.h17
-rw-r--r--tools/driver/ELWrapper.cpp422
-rw-r--r--tools/driver/ELWrapper.h122
-rw-r--r--tools/driver/GetOptWrapper.cpp33
-rw-r--r--tools/driver/GetOptWrapper.h49
-rw-r--r--tools/driver/IOChannel.cpp121
-rw-r--r--tools/driver/IOChannel.h42
-rw-r--r--tools/driver/Platform.cpp111
-rw-r--r--tools/driver/Platform.h113
-rw-r--r--tools/lldb-platform/lldb-platform.cpp270
421 files changed, 26615 insertions, 7987 deletions
diff --git a/include/lldb/API/SBHostOS.h b/include/lldb/API/SBHostOS.h
index 52754ea4e829..e5fab6fe7849 100644
--- a/include/lldb/API/SBHostOS.h
+++ b/include/lldb/API/SBHostOS.h
@@ -30,7 +30,7 @@ public:
static lldb::thread_t
ThreadCreate (const char *name,
- void *(*thread_function)(void *),
+ thread_func_t thread_function,
void *thread_arg,
lldb::SBError *err);
@@ -43,7 +43,7 @@ public:
lldb::SBError *err);
static bool
ThreadJoin (lldb::thread_t thread,
- void **result,
+ thread_result_t *result,
lldb::SBError *err);
diff --git a/include/lldb/API/SBProcess.h b/include/lldb/API/SBProcess.h
index 784f362122a9..4ecaeaa49920 100644
--- a/include/lldb/API/SBProcess.h
+++ b/include/lldb/API/SBProcess.h
@@ -269,6 +269,38 @@ public:
lldb::SBError
UnloadImage (uint32_t image_token);
+ //------------------------------------------------------------------
+ /// Return the number of different thread-origin extended backtraces
+ /// this process can support.
+ ///
+ /// When the process is stopped and you have an SBThread, lldb may be
+ /// able to show a backtrace of when that thread was originally created,
+ /// or the work item was enqueued to it (in the case of a libdispatch
+ /// queue).
+ ///
+ /// @return
+ /// The number of thread-origin extended backtrace types that may be
+ /// available.
+ //------------------------------------------------------------------
+ uint32_t
+ GetNumExtendedBacktraceTypes ();
+
+ //------------------------------------------------------------------
+ /// Return the name of one of the thread-origin extended backtrace
+ /// methods.
+ ///
+ /// @param [in] idx
+ /// The index of the name to return. They will be returned in
+ /// the order that the user will most likely want to see them.
+ /// e.g. if the type at index 0 is not available for a thread,
+ /// see if the type at index 1 provides an extended backtrace.
+ ///
+ /// @return
+ /// The name at that index.
+ //------------------------------------------------------------------
+ const char *
+ GetExtendedBacktraceTypeAtIndex (uint32_t idx);
+
protected:
friend class SBAddress;
friend class SBBreakpoint;
diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h
index 15aeed4b600c..7bcf91c16d77 100644
--- a/include/lldb/API/SBTarget.h
+++ b/include/lldb/API/SBTarget.h
@@ -747,6 +747,9 @@ public:
lldb::SBType
GetBasicType(lldb::BasicType type);
+ lldb::SBValue
+ CreateValueFromAddress (const char *name, lldb::SBAddress addr, lldb::SBType type);
+
SBSourceManager
GetSourceManager();
diff --git a/include/lldb/API/SBThread.h b/include/lldb/API/SBThread.h
index 9645f925035e..d062d7121303 100644
--- a/include/lldb/API/SBThread.h
+++ b/include/lldb/API/SBThread.h
@@ -94,6 +94,9 @@ public:
const char *
GetQueueName() const;
+ lldb::queue_id_t
+ GetQueueID() const;
+
void
StepOver (lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping);
@@ -117,6 +120,9 @@ public:
lldb::SBFileSpec &file_spec,
uint32_t line);
+ SBError
+ JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line);
+
void
RunToAddress (lldb::addr_t addr);
@@ -195,6 +201,9 @@ public:
bool
GetStatus (lldb::SBStream &status) const;
+ SBThread
+ GetExtendedBacktrace (const char *type);
+
protected:
friend class SBBreakpoint;
friend class SBBreakpointLocation;
diff --git a/include/lldb/Breakpoint/Breakpoint.h b/include/lldb/Breakpoint/Breakpoint.h
index bd11a1c91e21..30cc3314af3a 100644
--- a/include/lldb/Breakpoint/Breakpoint.h
+++ b/include/lldb/Breakpoint/Breakpoint.h
@@ -576,6 +576,12 @@ public:
InvokeCallback (StoppointCallbackContext *context,
lldb::break_id_t bp_loc_id);
+ bool
+ IsHardware() const
+ {
+ return m_hardware;
+ }
+
protected:
friend class Target;
//------------------------------------------------------------------
@@ -590,7 +596,10 @@ protected:
/// variants that make breakpoints for some common cases.
//------------------------------------------------------------------
// This is the generic constructor
- Breakpoint(Target &target, lldb::SearchFilterSP &filter_sp, lldb::BreakpointResolverSP &resolver_sp);
+ Breakpoint(Target &target,
+ lldb::SearchFilterSP &filter_sp,
+ lldb::BreakpointResolverSP &resolver_sp,
+ bool hardware);
friend class BreakpointLocation; // To call the following two when determining whether to stop.
@@ -609,12 +618,13 @@ private:
// For Breakpoint only
//------------------------------------------------------------------
bool m_being_created;
+ bool m_hardware; // If this breakpoint is required to use a hardware breakpoint
Target &m_target; // The target that holds this breakpoint.
lldb::SearchFilterSP m_filter_sp; // The filter that constrains the breakpoint's domain.
lldb::BreakpointResolverSP m_resolver_sp; // The resolver that defines this breakpoint.
BreakpointOptions m_options; // Settable breakpoint options
BreakpointLocationList m_locations; // The list of locations currently found for this breakpoint.
- std::string m_kind_description;
+ std::string m_kind_description;
void
SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind);
diff --git a/include/lldb/Breakpoint/BreakpointList.h b/include/lldb/Breakpoint/BreakpointList.h
index 97eb2b46bc0c..c6708db118df 100644
--- a/include/lldb/Breakpoint/BreakpointList.h
+++ b/include/lldb/Breakpoint/BreakpointList.h
@@ -149,11 +149,17 @@ public:
/// @param[in] module_list
/// The module list that has changed.
///
- /// @param[in] added
+ /// @param[in] load
/// \b true if the modules are loaded, \b false if unloaded.
+ ///
+ /// @param[in] delete_locations
+ /// If \a load is \b false, then delete breakpoint locations when
+ /// when updating breakpoints.
//------------------------------------------------------------------
void
- UpdateBreakpoints (ModuleList &module_list, bool added);
+ UpdateBreakpoints (ModuleList &module_list,
+ bool load,
+ bool delete_locations);
void
UpdateBreakpointsWhenModuleIsReplaced (lldb::ModuleSP old_module_sp, lldb::ModuleSP new_module_sp);
diff --git a/include/lldb/Breakpoint/BreakpointLocation.h b/include/lldb/Breakpoint/BreakpointLocation.h
index 9ab0a79c6844..f4ba21a385f8 100644
--- a/include/lldb/Breakpoint/BreakpointLocation.h
+++ b/include/lldb/Breakpoint/BreakpointLocation.h
@@ -324,7 +324,6 @@ public:
protected:
friend class BreakpointLocationList;
- friend class CommandObjectBreakpointCommandAdd;
friend class Process;
//------------------------------------------------------------------
@@ -375,8 +374,8 @@ private:
BreakpointLocation (lldb::break_id_t bid,
Breakpoint &owner,
const Address &addr,
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID,
- bool hardware = false);
+ lldb::tid_t tid,
+ bool hardware);
//------------------------------------------------------------------
// Data members:
diff --git a/include/lldb/Breakpoint/BreakpointResolver.h b/include/lldb/Breakpoint/BreakpointResolver.h
index 3db3795453e8..184bdc950cbc 100644
--- a/include/lldb/Breakpoint/BreakpointResolver.h
+++ b/include/lldb/Breakpoint/BreakpointResolver.h
@@ -134,6 +134,13 @@ public:
}
protected:
+ //------------------------------------------------------------------
+ /// SetSCMatchesByLine - Takes a symbol context list of matches which supposedly represent the same file and
+ /// line number in a CU, and find the nearest actual line number that matches, and then filter down the
+ /// matching addresses to unique entries, and skip the prologue if asked to do so, and then set
+ /// breakpoint locations in this breakpoint for all the resultant addresses.
+ void SetSCMatchesByLine (SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, const char *log_ident);
+
Breakpoint *m_breakpoint; // This is the breakpoint we add locations to.
private:
diff --git a/include/lldb/Breakpoint/BreakpointSiteList.h b/include/lldb/Breakpoint/BreakpointSiteList.h
index 0d4dafc4baab..d7bb8fd777ef 100644
--- a/include/lldb/Breakpoint/BreakpointSiteList.h
+++ b/include/lldb/Breakpoint/BreakpointSiteList.h
@@ -13,6 +13,7 @@
// C Includes
// C++ Includes
#include <map>
+#include <functional>
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointSite.h"
diff --git a/include/lldb/Breakpoint/StoppointLocation.h b/include/lldb/Breakpoint/StoppointLocation.h
index ccedc511951d..452c6388c82d 100644
--- a/include/lldb/Breakpoint/StoppointLocation.h
+++ b/include/lldb/Breakpoint/StoppointLocation.h
@@ -72,20 +72,20 @@ public:
uint32_t
GetHardwareIndex () const
{
- return m_hw_index;
+ return m_hardware_index;
}
bool
- HardwarePreferred () const
+ HardwareRequired () const
{
- return m_hw_preferred;
+ return m_hardware;
}
virtual bool
IsHardware () const
{
- return m_hw_index != LLDB_INVALID_INDEX32;
+ return m_hardware_index != LLDB_INVALID_INDEX32;
}
@@ -103,7 +103,7 @@ public:
void
SetHardwareIndex (uint32_t index)
{
- m_hw_index = index;
+ m_hardware_index = index;
}
@@ -120,8 +120,8 @@ protected:
lldb::break_id_t m_loc_id; // Stoppoint location ID
lldb::addr_t m_addr; // The load address of this stop point. The base Stoppoint doesn't
// store a full Address since that's not needed for the breakpoint sites.
- bool m_hw_preferred; // 1 if this point has been requested to be set using hardware (which may fail due to lack of resources)
- uint32_t m_hw_index; // The hardware resource index for this breakpoint/watchpoint
+ bool m_hardware; // True if this point has been is required to use hardware (which may fail due to lack of resources)
+ uint32_t m_hardware_index; // The hardware resource index for this breakpoint/watchpoint
uint32_t m_byte_size; // The size in bytes of stop location. e.g. the length of the trap opcode for
// software breakpoints, or the optional length in bytes for
// hardware breakpoints, or the length of the watchpoint.
diff --git a/include/lldb/Core/Address.h b/include/lldb/Core/Address.h
index 60cd4a86bd4a..da7cc5c03d38 100644
--- a/include/lldb/Core/Address.h
+++ b/include/lldb/Core/Address.h
@@ -540,6 +540,18 @@ protected:
//------------------------------------------------------------------
lldb::SectionWP m_section_wp; ///< The section for the address, can be NULL.
std::atomic<lldb::addr_t> m_offset; ///< Offset into section if \a m_section_wp is valid...
+
+ //------------------------------------------------------------------
+ // Returns true if the m_section_wp once had a reference to a valid
+ // section shared pointer, but no longer does. This can happen if
+ // we have an address from a module that gets unloaded and deleted.
+ // This function should only be called if GetSection() returns an
+ // empty shared pointer and you want to know if this address used to
+ // have a valid section.
+ //------------------------------------------------------------------
+ bool
+ SectionWasDeleted() const;
+
};
diff --git a/include/lldb/Core/ArchSpec.h b/include/lldb/Core/ArchSpec.h
index 3bfa96be0cee..7f2fd77a0934 100644
--- a/include/lldb/Core/ArchSpec.h
+++ b/include/lldb/Core/ArchSpec.h
@@ -41,6 +41,7 @@ public:
eCore_arm_armv5e,
eCore_arm_armv5t,
eCore_arm_armv6,
+ eCore_arm_armv6m,
eCore_arm_armv7,
eCore_arm_armv7f,
eCore_arm_armv7s,
@@ -53,6 +54,7 @@ public:
eCore_thumbv5,
eCore_thumbv5e,
eCore_thumbv6,
+ eCore_thumbv6m,
eCore_thumbv7,
eCore_thumbv7f,
eCore_thumbv7s,
@@ -60,6 +62,8 @@ public:
eCore_thumbv7m,
eCore_thumbv7em,
+ eCore_mips64,
+
eCore_ppc_generic,
eCore_ppc_ppc601,
eCore_ppc_ppc602,
diff --git a/include/lldb/Core/ConnectionFileDescriptor.h b/include/lldb/Core/ConnectionFileDescriptor.h
index fe704d4cadf7..3a2f0dd1ed0b 100644
--- a/include/lldb/Core/ConnectionFileDescriptor.h
+++ b/include/lldb/Core/ConnectionFileDescriptor.h
@@ -11,20 +11,27 @@
#define liblldb_ConnectionFileDescriptor_h_
// C Includes
+#ifdef _WIN32
+typedef unsigned short in_port_t;
+#else
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
+#endif
// C++ Includes
+#include <memory>
+
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Connection.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Host/Predicate.h"
-#include "lldb/Host/SocketAddress.h"
namespace lldb_private {
+class SocketAddress;
+
class ConnectionFileDescriptor :
public Connection
{
@@ -70,6 +77,13 @@ public:
GetWritePort () const;
protected:
+
+ typedef enum
+ {
+ eFDTypeFile, // Other FD requireing read/write
+ eFDTypeSocket, // Socket requiring send/recv
+ eFDTypeSocketUDP // Unconnected UDP socket requiring sendto/recvfrom
+ } FDType;
void
OpenCommandPipe ();
@@ -96,20 +110,13 @@ protected:
NamedSocketConnect (const char *socket_name, Error *error_ptr);
lldb::ConnectionStatus
- Close (int& fd, Error *error);
-
- typedef enum
- {
- eFDTypeFile, // Other FD requireing read/write
- eFDTypeSocket, // Socket requiring send/recv
- eFDTypeSocketUDP // Unconnected UDP socket requiring sendto/recvfrom
- } FDType;
+ Close (int& fd, FDType type, Error *error);
int m_fd_send;
int m_fd_recv;
FDType m_fd_send_type;
FDType m_fd_recv_type;
- SocketAddress m_udp_send_sockaddr;
+ std::unique_ptr<SocketAddress> m_udp_send_sockaddr;
bool m_should_close_fd; // True if this class should close the file descriptor when it goes away.
uint32_t m_socket_timeout_usec;
int m_pipe_read; // A pipe that we select on the reading end of along with
diff --git a/include/lldb/Core/ConnectionMachPort.h b/include/lldb/Core/ConnectionMachPort.h
index 5613e7ee8008..04ec7f69136b 100644
--- a/include/lldb/Core/ConnectionMachPort.h
+++ b/include/lldb/Core/ConnectionMachPort.h
@@ -12,7 +12,8 @@
#define liblldb_ConnectionMachPort_h_
// C Includes
-#include <mach/mach.h>
+#include <mach/port.h>
+#include <mach/kern_return.h>
// C++ Includes
#include <string>
diff --git a/include/lldb/Core/ConstString.h b/include/lldb/Core/ConstString.h
index e692d3b96e5d..684cc8f921ed 100644
--- a/include/lldb/Core/ConstString.h
+++ b/include/lldb/Core/ConstString.h
@@ -86,7 +86,7 @@ public:
/// @param[in] cstr
/// A pointer to the first character in the C string. The C
/// string can be NULL terminated in a buffer that contains
- /// more characters than the length of the stirng, or the
+ /// more characters than the length of the string, or the
/// string can be part of another string and a new substring
/// can be created.
///
@@ -148,11 +148,11 @@ public:
/// /b True this object contains a valid non-empty C string, \b
/// false otherwise.
//------------------------------------------------------------------
- operator bool() const
+ explicit operator bool() const
{
return m_string && m_string[0];
}
-
+
//------------------------------------------------------------------
/// Assignment operator
///
diff --git a/include/lldb/Core/DataExtractor.h b/include/lldb/Core/DataExtractor.h
index a8593043cb15..c9db2dab73d2 100644
--- a/include/lldb/Core/DataExtractor.h
+++ b/include/lldb/Core/DataExtractor.h
@@ -468,6 +468,27 @@ public:
}
//------------------------------------------------------------------
+ /// Copy \a length bytes from \a *offset, without swapping bytes.
+ ///
+ /// @param[in] offset
+ /// The offset into this data from which to start copying
+ ///
+ /// @param[in] length
+ /// The length of the data to copy from this object
+ ///
+ /// @param[out] dst
+ /// The buffer to place the output data.
+ ///
+ /// @return
+ /// Returns the number of bytes that were copied, or zero if
+ /// anything goes wrong.
+ //------------------------------------------------------------------
+ lldb::offset_t
+ CopyData (lldb::offset_t offset,
+ lldb::offset_t length,
+ void *dst) const;
+
+ //------------------------------------------------------------------
/// Copy \a dst_len bytes from \a *offset_ptr and ensure the copied
/// data is treated as a value that can be swapped to match the
/// specified byte order.
diff --git a/include/lldb/Core/Debugger.h b/include/lldb/Core/Debugger.h
index bed93fe02528..671b378df807 100644
--- a/include/lldb/Core/Debugger.h
+++ b/include/lldb/Core/Debugger.h
@@ -13,7 +13,6 @@
#include <stdint.h>
-#include <unistd.h>
#include <stack>
@@ -323,6 +322,9 @@ public:
GetDisassemblyLineCount () const;
bool
+ GetAutoOneLineSummaries () const;
+
+ bool
GetNotifyVoid () const;
diff --git a/include/lldb/Core/Disassembler.h b/include/lldb/Core/Disassembler.h
index d6e90071dc5b..f434d56943d4 100644
--- a/include/lldb/Core/Disassembler.h
+++ b/include/lldb/Core/Disassembler.h
@@ -270,7 +270,8 @@ public:
const char *plugin_name,
const char *flavor,
const ExecutionContext &exe_ctx,
- const AddressRange &disasm_range);
+ const AddressRange &disasm_range,
+ bool prefer_file_cache);
static lldb::DisassemblerSP
DisassembleBytes (const ArchSpec &arch,
diff --git a/include/lldb/Core/EmulateInstruction.h b/include/lldb/Core/EmulateInstruction.h
index 08b97e424913..19a3269ae374 100644
--- a/include/lldb/Core/EmulateInstruction.h
+++ b/include/lldb/Core/EmulateInstruction.h
@@ -69,14 +69,14 @@
/// debugging. The current debugging model is "process centric" where
/// all threads must be stopped when any thread is stopped; when
/// hitting software breakpoints we must disable the breakpoint by
-/// restoring the original breakpoint opcde, single stepping and
+/// restoring the original breakpoint opcode, single stepping and
/// restoring the breakpoint trap. If all threads were allowed to run
/// then other threads could miss the breakpoint.
///
/// This class centralizes the code that usually is done in separate
/// code paths in a debugger (single step prediction, finding save
/// restore locations of registers for unwinding stack frame variables)
-/// and emulating the intruction is just a bonus.
+/// and emulating the instruction is just a bonus.
//----------------------------------------------------------------------
namespace lldb_private {
@@ -394,7 +394,7 @@ public:
// Mandatory overrides
//----------------------------------------------------------------------
virtual bool
- SupportsEmulatingIntructionsOfType (InstructionType inst_type) = 0;
+ SupportsEmulatingInstructionsOfType (InstructionType inst_type) = 0;
virtual bool
SetTargetTriple (const ArchSpec &arch) = 0;
diff --git a/include/lldb/Core/Error.h b/include/lldb/Core/Error.h
index 9e45d5f555d6..39c67f621c92 100644
--- a/include/lldb/Core/Error.h
+++ b/include/lldb/Core/Error.h
@@ -11,11 +11,10 @@
#define __DCError_h__
#if defined(__cplusplus)
-#if defined (__APPLE__)
-#include <mach/mach.h>
-#endif
-#include <stdint.h>
-#include <stdio.h>
+#include "llvm/Support/DataTypes.h"
+
+#include <cstdarg>
+#include <cstdio>
#include <string>
#include "lldb/lldb-private.h"
@@ -70,7 +69,7 @@ public:
Error (ValueType err, lldb::ErrorType type = lldb::eErrorTypeGeneric);
explicit
- Error (const char* err_str);
+ Error (const char *format, ...) __attribute__ ((format (printf, 2, 3)));
Error (const Error &rhs);
//------------------------------------------------------------------
diff --git a/include/lldb/Core/Flags.h b/include/lldb/Core/Flags.h
index 233f098ead23..5f4f8830456b 100644
--- a/include/lldb/Core/Flags.h
+++ b/include/lldb/Core/Flags.h
@@ -13,7 +13,6 @@
#include <stdint.h>
-#include <unistd.h>
namespace lldb_private {
diff --git a/include/lldb/Core/Log.h b/include/lldb/Core/Log.h
index ced6f2565d9a..b389946e264c 100644
--- a/include/lldb/Core/Log.h
+++ b/include/lldb/Core/Log.h
@@ -11,11 +11,10 @@
#define liblldb_Log_h_
// C Includes
-#include <stdbool.h>
+#include <stdarg.h>
#include <stdint.h>
#include <signal.h>
#include <stdio.h>
-#include <unistd.h>
// C++ Includes
// Other libraries and framework includes
diff --git a/include/lldb/Core/Module.h b/include/lldb/Core/Module.h
index 9c135529f453..1473fb90cf85 100644
--- a/include/lldb/Core/Module.h
+++ b/include/lldb/Core/Module.h
@@ -347,6 +347,32 @@ public:
SymbolContextList& sc_list);
//------------------------------------------------------------------
+ /// Find addresses by file/line
+ ///
+ /// @param[in] target_sp
+ /// The target the addresses are desired for.
+ ///
+ /// @param[in] file
+ /// Source file to locate.
+ ///
+ /// @param[in] line
+ /// Source line to locate.
+ ///
+ /// @param[in] function
+ /// Optional filter function. Addresses within this function will be
+ /// added to the 'local' list. All others will be added to the 'extern' list.
+ ///
+ /// @param[out] output_local
+ /// All matching addresses within 'function'
+ ///
+ /// @param[out] output_extern
+ /// All matching addresses not within 'function'
+ void FindAddressesForLine (const lldb::TargetSP target_sp,
+ const FileSpec &file, uint32_t line,
+ Function *function,
+ std::vector<Address> &output_local, std::vector<Address> &output_extern);
+
+ //------------------------------------------------------------------
/// Find global and static variables by name.
///
/// @param[in] name
@@ -723,8 +749,49 @@ public:
bool
ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr);
+ //------------------------------------------------------------------
+ /// Resolve the symbol context for the given address.
+ ///
+ /// Tries to resolve the matching symbol context based on a lookup
+ /// from the current symbol vendor. If the lazy lookup fails,
+ /// an attempt is made to parse the eh_frame section to handle
+ /// stripped symbols. If this fails, an attempt is made to resolve
+ /// the symbol to the previous address to handle the case of a
+ /// function with a tail call.
+ ///
+ /// Use properties of the modified SymbolContext to inspect any
+ /// resolved target, module, compilation unit, symbol, function,
+ /// function block or line entry. Use the return value to determine
+ /// which of these properties have been modified.
+ ///
+ /// @param[in] so_addr
+ /// A load address to resolve.
+ ///
+ /// @param[in] resolve_scope
+ /// The scope that should be resolved (see SymbolContext::Scope).
+ /// A combination of flags from the enumeration SymbolContextItem
+ /// requesting a resolution depth. Note that the flags that are
+ /// actually resolved may be a superset of the requested flags.
+ /// For instance, eSymbolContextSymbol requires resolution of
+ /// eSymbolContextModule, and eSymbolContextFunction requires
+ /// eSymbolContextSymbol.
+ ///
+ /// @param[out] sc
+ /// The SymbolContext that is modified based on symbol resolution.
+ ///
+ /// @param[in] resolve_tail_call_address
+ /// Determines if so_addr should resolve to a symbol in the case
+ /// of a function whose last instruction is a call. In this case,
+ /// the PC can be one past the address range of the function.
+ ///
+ /// @return
+ /// The scope that has been resolved (see SymbolContext::Scope).
+ ///
+ /// @see SymbolContext::Scope
+ //------------------------------------------------------------------
uint32_t
- ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc);
+ ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope,
+ SymbolContext& sc, bool resolve_tail_call_address = false);
//------------------------------------------------------------------
/// Resolve items in the symbol context for a given file and line.
diff --git a/include/lldb/Core/ModuleList.h b/include/lldb/Core/ModuleList.h
index 1198e4196481..f03f79fb00ce 100644
--- a/include/lldb/Core/ModuleList.h
+++ b/include/lldb/Core/ModuleList.h
@@ -439,7 +439,35 @@ public:
bool
FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const;
-
+
+
+ //------------------------------------------------------------------
+ /// Find addresses by file/line
+ ///
+ /// @param[in] target_sp
+ /// The target the addresses are desired for.
+ ///
+ /// @param[in] file
+ /// Source file to locate.
+ ///
+ /// @param[in] line
+ /// Source line to locate.
+ ///
+ /// @param[in] function
+ /// Optional filter function. Addresses within this function will be
+ /// added to the 'local' list. All others will be added to the 'extern' list.
+ ///
+ /// @param[out] output_local
+ /// All matching addresses within 'function'
+ ///
+ /// @param[out] output_extern
+ /// All matching addresses not within 'function'
+ void FindAddressesForLine (const lldb::TargetSP target_sp,
+ const FileSpec &file, uint32_t line,
+ Function *function,
+ std::vector<Address> &output_local, std::vector<Address> &output_extern);
+
+
bool
Remove (const lldb::ModuleSP &module_sp);
diff --git a/include/lldb/Core/ModuleSpec.h b/include/lldb/Core/ModuleSpec.h
index 10e1ea9f17a9..dfeb7b73ca37 100644
--- a/include/lldb/Core/ModuleSpec.h
+++ b/include/lldb/Core/ModuleSpec.h
@@ -288,7 +288,7 @@ public:
}
- operator bool () const
+ explicit operator bool () const
{
if (m_file)
return true;
diff --git a/include/lldb/Core/Opcode.h b/include/lldb/Core/Opcode.h
index c07193b62059..fd80231a44e7 100644
--- a/include/lldb/Core/Opcode.h
+++ b/include/lldb/Core/Opcode.h
@@ -38,7 +38,7 @@ namespace lldb_private {
eType64,
eTypeBytes
};
-
+
Opcode () : m_type (eTypeInvalid)
{
}
@@ -78,7 +78,7 @@ namespace lldb_private {
{
return m_type;
}
-
+
uint8_t
GetOpcode8 (uint8_t invalid_opcode = UINT8_MAX) const
{
@@ -91,7 +91,6 @@ namespace lldb_private {
case Opcode::eType32: break;
case Opcode::eType64: break;
case Opcode::eTypeBytes: break;
- break;
}
return invalid_opcode;
}
@@ -157,7 +156,7 @@ namespace lldb_private {
m_type = eType16;
m_data.inst16 = inst;
}
-
+
void
SetOpcode16_2 (uint32_t inst)
{
@@ -206,7 +205,7 @@ namespace lldb_private {
return m_data.inst.bytes;
return NULL;
}
-
+
uint32_t
GetByteSize () const
{
@@ -222,7 +221,7 @@ namespace lldb_private {
}
return 0;
}
-
+
// Get the opcode exactly as it would be laid out in memory.
uint32_t
GetData (DataExtractor &data) const;
@@ -246,7 +245,7 @@ namespace lldb_private {
}
return NULL;
}
-
+
lldb::ByteOrder
GetDataByteOrder () const;
@@ -257,7 +256,7 @@ namespace lldb_private {
uint16_t inst16;
uint32_t inst32;
uint64_t inst64;
- struct
+ struct
{
uint8_t bytes[16]; // This must be big enough to handle any opcode for any supported target.
uint8_t length;
diff --git a/include/lldb/Core/PluginManager.h b/include/lldb/Core/PluginManager.h
index 91f8fbb997f9..e02f43f4fa8b 100644
--- a/include/lldb/Core/PluginManager.h
+++ b/include/lldb/Core/PluginManager.h
@@ -132,6 +132,24 @@ public:
//------------------------------------------------------------------
+ // SystemRuntime
+ //------------------------------------------------------------------
+ static bool
+ RegisterPlugin (const ConstString &name,
+ const char *description,
+ SystemRuntimeCreateInstance create_callback);
+
+ static bool
+ UnregisterPlugin (SystemRuntimeCreateInstance create_callback);
+
+ static SystemRuntimeCreateInstance
+ GetSystemRuntimeCreateCallbackAtIndex (uint32_t idx);
+
+ static SystemRuntimeCreateInstance
+ GetSystemRuntimeCreateCallbackForPluginName (const ConstString &name);
+
+
+ //------------------------------------------------------------------
// ObjectFile
//------------------------------------------------------------------
static bool
diff --git a/include/lldb/Core/RangeMap.h b/include/lldb/Core/RangeMap.h
index ee42467c18bf..d78504c7d285 100644
--- a/include/lldb/Core/RangeMap.h
+++ b/include/lldb/Core/RangeMap.h
@@ -592,7 +592,7 @@ namespace lldb_private {
void
Reserve (typename Collection::size_type size)
{
- m_entries.resize (size);
+ m_entries.reserve (size);
}
bool
@@ -1229,16 +1229,11 @@ namespace lldb_private {
typename Collection::const_iterator end = m_entries.end();
typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
+ while(pos != begin && pos[-1].Contains(addr))
+ --pos;
+
if (pos != end && pos->Contains(addr))
- {
return std::distance (begin, pos);
- }
- else if (pos != begin)
- {
- --pos;
- if (pos->Contains(addr))
- return std::distance (begin, pos);
- }
}
return UINT32_MAX;
}
@@ -1257,19 +1252,12 @@ namespace lldb_private {
typename Collection::iterator begin = m_entries.begin();
typename Collection::iterator end = m_entries.end();
typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
+
+ while(pos != begin && pos[-1].Contains(addr))
+ --pos;
if (pos != end && pos->Contains(addr))
- {
return &(*pos);
- }
- else if (pos != begin)
- {
- --pos;
- if (pos->Contains(addr))
- {
- return &(*pos);
- }
- }
}
return NULL;
}
@@ -1288,18 +1276,11 @@ namespace lldb_private {
typename Collection::const_iterator end = m_entries.end();
typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
- if (pos != end && pos->Contains(addr))
- {
- return &(*pos);
- }
- else if (pos != begin)
- {
+ while(pos != begin && pos[-1].Contains(addr))
--pos;
- if (pos->Contains(addr))
- {
- return &(*pos);
- }
- }
+
+ if (pos != end && pos->Contains(addr))
+ return &(*pos);
}
return NULL;
}
@@ -1316,18 +1297,11 @@ namespace lldb_private {
typename Collection::const_iterator end = m_entries.end();
typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
- if (pos != end && pos->Contains(range))
- {
- return &(*pos);
- }
- else if (pos != begin)
- {
+ while(pos != begin && pos[-1].Contains(range))
--pos;
- if (pos->Contains(range))
- {
- return &(*pos);
- }
- }
+
+ if (pos != end && pos->Contains(range))
+ return &(*pos);
}
return NULL;
}
@@ -1501,12 +1475,15 @@ namespace lldb_private {
typename Collection::iterator end = m_entries.end();
typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
+ while(pos != begin && pos[-1].addr == addr)
+ --pos;
+
if (pos != end)
{
if (pos->addr == addr || !exact_match_only)
return &(*pos);
}
- }
+ }
return NULL;
}
diff --git a/include/lldb/Core/RegularExpression.h b/include/lldb/Core/RegularExpression.h
index eeeb914bfa90..c116d439b94a 100644
--- a/include/lldb/Core/RegularExpression.h
+++ b/include/lldb/Core/RegularExpression.h
@@ -11,7 +11,36 @@
#define liblldb_DBRegex_h_
#if defined(__cplusplus)
+#ifdef _WIN32
+#include "../lib/Support/regex_impl.h"
+
+typedef llvm_regmatch_t regmatch_t;
+typedef llvm_regex_t regex_t;
+
+inline int regcomp(llvm_regex_t * a, const char *b, int c)
+{
+ return llvm_regcomp(a, b, c);
+}
+
+inline size_t regerror(int a, const llvm_regex_t *b, char *c, size_t d)
+{
+ return llvm_regerror(a, b, c, d);
+}
+
+inline int regexec(const llvm_regex_t * a, const char * b, size_t c,
+ llvm_regmatch_t d [], int e)
+{
+ return llvm_regexec(a, b, c, d, e);
+}
+
+inline void regfree(llvm_regex_t * a)
+{
+ llvm_regfree(a);
+}
+
+#else
#include <regex.h>
+#endif
#include <stdint.h>
#include <string>
diff --git a/include/lldb/Core/StreamGDBRemote.h b/include/lldb/Core/StreamGDBRemote.h
new file mode 100644
index 000000000000..3fdb6f6e7012
--- /dev/null
+++ b/include/lldb/Core/StreamGDBRemote.h
@@ -0,0 +1,54 @@
+//===-- StreamGDBRemote.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_StreamGDBRemote_h_
+#define liblldb_StreamGDBRemote_h_
+
+// C Includes
+// C++ Includes
+
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/Core/StreamString.h"
+
+namespace lldb_private {
+
+ class StreamGDBRemote : public StreamString
+ {
+ public:
+ StreamGDBRemote ();
+
+ StreamGDBRemote (uint32_t flags,
+ uint32_t addr_size,
+ lldb::ByteOrder byte_order);
+
+ virtual
+ ~StreamGDBRemote ();
+
+ //------------------------------------------------------------------
+ /// Output a block of data to the stream performing GDB-remote escaping.
+ ///
+ /// @param[in] s
+ /// A block of data.
+ ///
+ /// @param[in] src_len
+ /// The amount of data to write.
+ ///
+ /// @return
+ /// Number of bytes written.
+ //------------------------------------------------------------------
+ int
+ PutEscapedBytes (const void* s,
+ size_t src_len);
+ };
+
+} // namespace lldb_private
+
+#endif // liblldb_StreamGDBRemote_h_
diff --git a/include/lldb/Core/UUID.h b/include/lldb/Core/UUID.h
index fe72b8eb0c70..3bb14421b1e9 100644
--- a/include/lldb/Core/UUID.h
+++ b/include/lldb/Core/UUID.h
@@ -12,6 +12,8 @@
// C Includes
// C++ Includes
+#include <string>
+
// Other libraries and framework includes
// Project includes
diff --git a/include/lldb/Core/Value.h b/include/lldb/Core/Value.h
index 5461ca73d082..c7d44322333c 100644
--- a/include/lldb/Core/Value.h
+++ b/include/lldb/Core/Value.h
@@ -114,7 +114,7 @@ public:
#if defined (ENABLE_128_BIT_SUPPORT)
else if (length >= 16) scalar = *(const __uint128_t *)bytes;
#else
- else if (length >= 16) scalar = *(const __uint64_t *)bytes;
+ else if (length >= 16) scalar = *(const uint64_t *)bytes;
#endif
}
return scalar;
diff --git a/include/lldb/Core/ValueObject.h b/include/lldb/Core/ValueObject.h
index 0d965d6ccc01..1ef421676ee1 100644
--- a/include/lldb/Core/ValueObject.h
+++ b/include/lldb/Core/ValueObject.h
@@ -12,7 +12,6 @@
// C Includes
// C++ Includes
-#include <initializer_list>
#include <map>
#include <vector>
// Other libraries and framework includes
@@ -217,229 +216,6 @@ public:
}
};
-
- struct DumpValueObjectOptions
- {
- uint32_t m_max_ptr_depth;
- uint32_t m_max_depth;
- bool m_show_types;
- bool m_show_location;
- bool m_use_objc;
- lldb::DynamicValueType m_use_dynamic;
- bool m_use_synthetic;
- bool m_scope_already_checked;
- bool m_flat_output;
- uint32_t m_omit_summary_depth;
- bool m_ignore_cap;
- lldb::Format m_format;
- lldb::TypeSummaryImplSP m_summary_sp;
- std::string m_root_valobj_name;
- bool m_hide_root_type;
- bool m_hide_name;
- bool m_hide_value;
-
- DumpValueObjectOptions() :
- m_max_ptr_depth(0),
- m_max_depth(UINT32_MAX),
- m_show_types(false),
- m_show_location(false),
- m_use_objc(false),
- m_use_dynamic(lldb::eNoDynamicValues),
- m_use_synthetic(true),
- m_scope_already_checked(false),
- m_flat_output(false),
- m_omit_summary_depth(0),
- m_ignore_cap(false),
- m_format (lldb::eFormatDefault),
- m_summary_sp(),
- m_root_valobj_name(),
- m_hide_root_type(false), // provide a special compact display for "po"
- m_hide_name(false), // provide a special compact display for "po"
- m_hide_value(false) // provide a special compact display for "po"
- {}
-
- static const DumpValueObjectOptions
- DefaultOptions()
- {
- static DumpValueObjectOptions g_default_options;
-
- return g_default_options;
- }
-
- DumpValueObjectOptions (const DumpValueObjectOptions& rhs) :
- m_max_ptr_depth(rhs.m_max_ptr_depth),
- m_max_depth(rhs.m_max_depth),
- m_show_types(rhs.m_show_types),
- m_show_location(rhs.m_show_location),
- m_use_objc(rhs.m_use_objc),
- m_use_dynamic(rhs.m_use_dynamic),
- m_use_synthetic(rhs.m_use_synthetic),
- m_scope_already_checked(rhs.m_scope_already_checked),
- m_flat_output(rhs.m_flat_output),
- m_omit_summary_depth(rhs.m_omit_summary_depth),
- m_ignore_cap(rhs.m_ignore_cap),
- m_format(rhs.m_format),
- m_summary_sp(rhs.m_summary_sp),
- m_root_valobj_name(rhs.m_root_valobj_name),
- m_hide_root_type(rhs.m_hide_root_type),
- m_hide_name(rhs.m_hide_name),
- m_hide_value(rhs.m_hide_value)
- {}
-
- DumpValueObjectOptions&
- SetMaximumPointerDepth(uint32_t depth = 0)
- {
- m_max_ptr_depth = depth;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetMaximumDepth(uint32_t depth = 0)
- {
- m_max_depth = depth;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetShowTypes(bool show = false)
- {
- m_show_types = show;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetShowLocation(bool show = false)
- {
- m_show_location = show;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetUseObjectiveC(bool use = false)
- {
- m_use_objc = use;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetShowSummary(bool show = true)
- {
- if (show == false)
- SetOmitSummaryDepth(UINT32_MAX);
- else
- SetOmitSummaryDepth(0);
- return *this;
- }
-
- DumpValueObjectOptions&
- SetUseDynamicType(lldb::DynamicValueType dyn = lldb::eNoDynamicValues)
- {
- m_use_dynamic = dyn;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetUseSyntheticValue(bool use_synthetic = true)
- {
- m_use_synthetic = use_synthetic;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetScopeChecked(bool check = true)
- {
- m_scope_already_checked = check;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetFlatOutput(bool flat = false)
- {
- m_flat_output = flat;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetOmitSummaryDepth(uint32_t depth = 0)
- {
- m_omit_summary_depth = depth;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetIgnoreCap(bool ignore = false)
- {
- m_ignore_cap = ignore;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetRawDisplay(bool raw = false)
- {
- if (raw)
- {
- SetUseSyntheticValue(false);
- SetOmitSummaryDepth(UINT32_MAX);
- SetIgnoreCap(true);
- SetHideName(false);
- SetHideValue(false);
- }
- else
- {
- SetUseSyntheticValue(true);
- SetOmitSummaryDepth(0);
- SetIgnoreCap(false);
- SetHideName(false);
- SetHideValue(false);
- }
- return *this;
- }
-
- DumpValueObjectOptions&
- SetFormat (lldb::Format format = lldb::eFormatDefault)
- {
- m_format = format;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetSummary (lldb::TypeSummaryImplSP summary = lldb::TypeSummaryImplSP())
- {
- m_summary_sp = summary;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetRootValueObjectName (const char* name = NULL)
- {
- if (name)
- m_root_valobj_name.assign(name);
- else
- m_root_valobj_name.clear();
- return *this;
- }
-
- DumpValueObjectOptions&
- SetHideRootType (bool hide_root_type = false)
- {
- m_hide_root_type = hide_root_type;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetHideName (bool hide_name = false)
- {
- m_hide_name = hide_name;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetHideValue (bool hide_value = false)
- {
- m_hide_value = hide_value;
- return *this;
- }
- };
class EvaluationPoint
{
@@ -598,6 +374,10 @@ public:
ClangASTType
GetClangType ();
+
+ // this vends a TypeImpl that is useful at the SB API layer
+ virtual TypeImpl
+ GetTypeImpl ();
//------------------------------------------------------------------
// Sublasses must implement the functions below.
@@ -725,6 +505,9 @@ public:
virtual uint64_t
GetValueAsUnsigned (uint64_t fail_value, bool *success = NULL);
+ virtual int64_t
+ GetValueAsSigned (int64_t fail_value, bool *success = NULL);
+
virtual bool
SetValueFromCString (const char *value_str, Error& error);
@@ -768,6 +551,23 @@ public:
lldb::ValueObjectSP
GetChildAtIndexPath (const std::vector< std::pair<size_t, bool> > &idxs,
size_t* index_of_error = NULL);
+
+ // this will always create the children if necessary
+ lldb::ValueObjectSP
+ GetChildAtNamePath (const std::initializer_list<ConstString> &names,
+ ConstString* name_of_error = NULL);
+
+ lldb::ValueObjectSP
+ GetChildAtNamePath (const std::vector<ConstString> &names,
+ ConstString* name_of_error = NULL);
+
+ lldb::ValueObjectSP
+ GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names,
+ ConstString* name_of_error = NULL);
+
+ lldb::ValueObjectSP
+ GetChildAtNamePath (const std::vector< std::pair<ConstString, bool> > &names,
+ ConstString* name_of_error = NULL);
virtual lldb::ValueObjectSP
GetChildMemberWithName (const ConstString &name, bool can_create);
@@ -937,13 +737,12 @@ public:
virtual SymbolContextScope *
GetSymbolContextScope();
- static void
- DumpValueObject (Stream &s,
- ValueObject *valobj);
- static void
- DumpValueObject (Stream &s,
- ValueObject *valobj,
- const DumpValueObjectOptions& options);
+ void
+ Dump (Stream &s);
+
+ void
+ Dump (Stream &s,
+ const DumpValueObjectOptions& options);
static lldb::ValueObjectSP
CreateValueObjectFromExpression (const char* name,
@@ -962,13 +761,11 @@ public:
const ExecutionContext& exe_ctx,
ClangASTType type);
- static void
- LogValueObject (Log *log,
- ValueObject *valobj);
+ void
+ LogValueObject (Log *log);
- static void
+ void
LogValueObject (Log *log,
- ValueObject *valobj,
const DumpValueObjectOptions& options);
diff --git a/include/lldb/Core/ValueObjectDynamicValue.h b/include/lldb/Core/ValueObjectDynamicValue.h
index c0f6baade3fb..68f88c96e545 100644
--- a/include/lldb/Core/ValueObjectDynamicValue.h
+++ b/include/lldb/Core/ValueObjectDynamicValue.h
@@ -93,6 +93,9 @@ public:
virtual bool
SetData (DataExtractor &data, Error &error);
+ virtual TypeImpl
+ GetTypeImpl ();
+
protected:
virtual bool
UpdateValue ();
@@ -116,6 +119,7 @@ protected:
TypeAndOrName m_dynamic_type_info; // We can have a type_sp or just a name
lldb::ValueObjectSP m_owning_valobj_sp;
lldb::DynamicValueType m_use_dynamic;
+ TypeImpl m_type_impl;
private:
friend class ValueObject;
diff --git a/include/lldb/Core/dwarf.h b/include/lldb/Core/dwarf.h
index bf77125d86a8..91c8dfb9d0da 100644
--- a/include/lldb/Core/dwarf.h
+++ b/include/lldb/Core/dwarf.h
@@ -11,7 +11,6 @@
#define DebugBase_dwarf_h_
#include <stdint.h>
-#include <stdbool.h>
// Get the DWARF constant defintions from llvm
#include "llvm/Support/Dwarf.h"
diff --git a/include/lldb/DataFormatters/CXXFormatterFunctions.h b/include/lldb/DataFormatters/CXXFormatterFunctions.h
index 2f56c56810ab..433c2a3c407b 100644
--- a/include/lldb/DataFormatters/CXXFormatterFunctions.h
+++ b/include/lldb/DataFormatters/CXXFormatterFunctions.h
@@ -868,6 +868,39 @@ namespace lldb_private {
SyntheticChildrenFrontEnd* LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+ class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~LibcxxStdUnorderedMapSyntheticFrontEnd ();
+ private:
+
+ ValueObject* m_tree;
+ size_t m_num_elements;
+ ValueObject* m_next_element;
+ std::map<size_t,lldb::ValueObjectSP> m_children;
+ std::vector<std::pair<ValueObject*, uint64_t> > m_elements_cache;
+ };
+
+ SyntheticChildrenFrontEnd* LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
} // namespace formatters
} // namespace lldb_private
diff --git a/include/lldb/DataFormatters/DataVisualization.h b/include/lldb/DataFormatters/DataVisualization.h
index 499e0fe14d93..ca0714c29f84 100644
--- a/include/lldb/DataFormatters/DataVisualization.h
+++ b/include/lldb/DataFormatters/DataVisualization.h
@@ -36,40 +36,19 @@ public:
static uint32_t
GetCurrentRevision ();
- class ValueFormats
- {
- public:
- static lldb::TypeFormatImplSP
- GetFormat (ValueObject& valobj, lldb::DynamicValueType use_dynamic);
-
- static lldb::TypeFormatImplSP
- GetFormat (const ConstString &type);
-
- static void
- Add (const ConstString &type, const lldb::TypeFormatImplSP &entry);
-
- static bool
- Delete (const ConstString &type);
-
- static void
- Clear ();
-
- static void
- LoopThrough (TypeFormatImpl::ValueCallback callback, void* callback_baton);
-
- static size_t
- GetCount ();
-
- static lldb::TypeNameSpecifierImplSP
- GetTypeNameSpecifierForFormatAtIndex (size_t);
-
- static lldb::TypeFormatImplSP
- GetFormatAtIndex (size_t);
- };
+ static bool
+ ShouldPrintAsOneLiner (ValueObject& valobj);
+
+ static lldb::TypeFormatImplSP
+ GetFormat (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic);
+
+ static lldb::TypeFormatImplSP
+ GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp);
static lldb::TypeSummaryImplSP
- GetSummaryFormat(ValueObject& valobj,
- lldb::DynamicValueType use_dynamic);
+ GetSummaryFormat (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic);
static lldb::TypeSummaryImplSP
GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp);
diff --git a/include/lldb/DataFormatters/FormatCache.h b/include/lldb/DataFormatters/FormatCache.h
index 941b96c1facc..bd9e20ccc9ee 100644
--- a/include/lldb/DataFormatters/FormatCache.h
+++ b/include/lldb/DataFormatters/FormatCache.h
@@ -27,23 +27,32 @@ private:
struct Entry
{
private:
+ bool m_format_cached : 1;
bool m_summary_cached : 1;
bool m_synthetic_cached : 1;
+ lldb::TypeFormatImplSP m_format_sp;
lldb::TypeSummaryImplSP m_summary_sp;
lldb::SyntheticChildrenSP m_synthetic_sp;
public:
Entry ();
+ Entry (lldb::TypeFormatImplSP);
Entry (lldb::TypeSummaryImplSP);
Entry (lldb::SyntheticChildrenSP);
- Entry (lldb::TypeSummaryImplSP,lldb::SyntheticChildrenSP);
+ Entry (lldb::TypeFormatImplSP,lldb::TypeSummaryImplSP,lldb::SyntheticChildrenSP);
bool
+ IsFormatCached ();
+
+ bool
IsSummaryCached ();
bool
IsSyntheticCached ();
+ lldb::TypeFormatImplSP
+ GetFormat ();
+
lldb::TypeSummaryImplSP
GetSummary ();
@@ -51,6 +60,9 @@ private:
GetSynthetic ();
void
+ SetFormat (lldb::TypeFormatImplSP);
+
+ void
SetSummary (lldb::TypeSummaryImplSP);
void
@@ -70,12 +82,18 @@ public:
FormatCache ();
bool
+ GetFormat (const ConstString& type,lldb::TypeFormatImplSP& format_sp);
+
+ bool
GetSummary (const ConstString& type,lldb::TypeSummaryImplSP& summary_sp);
bool
GetSynthetic (const ConstString& type,lldb::SyntheticChildrenSP& synthetic_sp);
void
+ SetFormat (const ConstString& type,lldb::TypeFormatImplSP& format_sp);
+
+ void
SetSummary (const ConstString& type,lldb::TypeSummaryImplSP& summary_sp);
void
diff --git a/include/lldb/DataFormatters/FormatClasses.h b/include/lldb/DataFormatters/FormatClasses.h
index 48a8eda4ad43..6d9a50e8f2c5 100644
--- a/include/lldb/DataFormatters/FormatClasses.h
+++ b/include/lldb/DataFormatters/FormatClasses.h
@@ -12,7 +12,6 @@
// C Includes
#include <stdint.h>
-#include <unistd.h>
// C++ Includes
#include <string>
@@ -61,7 +60,7 @@ public:
if (type)
{
m_type.m_type_name.assign(type->GetName().GetCString());
- m_type.m_typeimpl_sp = lldb::TypeImplSP(new TypeImpl(type));
+ m_type.m_type_pair.SetType(type);
}
}
@@ -72,7 +71,7 @@ public:
if (type.IsValid())
{
m_type.m_type_name.assign(type.GetConstTypeName().GetCString());
- m_type.m_typeimpl_sp = lldb::TypeImplSP(new TypeImpl(type));
+ m_type.m_type_pair.SetType(type);
}
}
@@ -87,16 +86,16 @@ public:
lldb::TypeSP
GetTypeSP ()
{
- if (m_type.m_typeimpl_sp && m_type.m_typeimpl_sp->IsValid())
- return m_type.m_typeimpl_sp->GetTypeSP();
+ if (m_type.m_type_pair.IsValid())
+ return m_type.m_type_pair.GetTypeSP();
return lldb::TypeSP();
}
ClangASTType
GetClangASTType ()
{
- if (m_type.m_typeimpl_sp && m_type.m_typeimpl_sp->IsValid())
- return m_type.m_typeimpl_sp->GetClangASTType();
+ if (m_type.m_type_pair.IsValid())
+ return m_type.m_type_pair.GetClangASTType();
return ClangASTType();
}
@@ -109,12 +108,11 @@ public:
private:
bool m_is_regex;
// this works better than TypeAndOrName because the latter only wraps a TypeSP
- // whereas TypeImplSP can also be backed by a ClangASTType which is more commonly
- // used in LLDB. moreover, TypeImplSP is also what is currently backing SBType
+ // whereas TypePair can also be backed by a ClangASTType
struct TypeOrName
{
std::string m_type_name;
- lldb::TypeImplSP m_typeimpl_sp;
+ TypePair m_type_pair;
};
TypeOrName m_type;
diff --git a/include/lldb/DataFormatters/FormatManager.h b/include/lldb/DataFormatters/FormatManager.h
index 162e25143f27..3c90c993e0c4 100644
--- a/include/lldb/DataFormatters/FormatManager.h
+++ b/include/lldb/DataFormatters/FormatManager.h
@@ -23,6 +23,8 @@
#include "lldb/DataFormatters/TypeCategory.h"
#include "lldb/DataFormatters/TypeCategoryMap.h"
+#include <atomic>
+
namespace lldb_private {
// this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization
@@ -32,8 +34,6 @@ namespace lldb_private {
class FormatManager : public IFormatChangeListener
{
- typedef FormatNavigator<ConstString, TypeFormatImpl> ValueNavigator;
- typedef ValueNavigator::MapType ValueMap;
typedef FormatMap<ConstString, TypeSummaryImpl> NamedSummariesMap;
typedef TypeCategoryMap::MapType::iterator CategoryMapIterator;
public:
@@ -42,12 +42,6 @@ public:
FormatManager ();
- ValueNavigator&
- GetValueNavigator ()
- {
- return m_value_nav;
- }
-
NamedSummariesMap&
GetNamedSummaryNavigator ()
{
@@ -124,6 +118,9 @@ public:
lldb::TypeCategoryImplSP
GetCategory (const ConstString& category_name,
bool can_create = true);
+
+ lldb::TypeFormatImplSP
+ GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp);
lldb::TypeSummaryImplSP
GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp);
@@ -141,6 +138,10 @@ public:
GetSyntheticChildrenForType (lldb::TypeNameSpecifierImplSP type_sp);
#endif
+ lldb::TypeFormatImplSP
+ GetFormat (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic);
+
lldb::TypeSummaryImplSP
GetSummaryFormat (ValueObject& valobj,
lldb::DynamicValueType use_dynamic);
@@ -188,10 +189,17 @@ public:
static lldb::Format
GetSingleItemFormat (lldb::Format vector_format);
+ // this returns true if the ValueObjectPrinter is *highly encouraged*
+ // to actually represent this ValueObject in one-liner format
+ // If this object has a summary formatter, however, we should not
+ // try and do one-lining, just let the summary do the right thing
+ bool
+ ShouldPrintAsOneLiner (ValueObject& valobj);
+
void
Changed ()
{
- __sync_add_and_fetch(&m_last_revision, +1);
+ ++m_last_revision;
m_format_cache.Clear ();
}
@@ -207,9 +215,8 @@ public:
private:
FormatCache m_format_cache;
- ValueNavigator m_value_nav;
NamedSummariesMap m_named_summaries_map;
- uint32_t m_last_revision;
+ std::atomic<uint32_t> m_last_revision;
TypeCategoryMap m_categories_map;
ConstString m_default_category_name;
diff --git a/include/lldb/DataFormatters/FormatNavigator.h b/include/lldb/DataFormatters/FormatNavigator.h
index a738cfd069e7..cd5f6824e199 100644
--- a/include/lldb/DataFormatters/FormatNavigator.h
+++ b/include/lldb/DataFormatters/FormatNavigator.h
@@ -76,7 +76,7 @@ GetValidTypeName_Impl (const ConstString& type)
{
int strip_len = 0;
- if (type == false)
+ if ((bool)type == false)
return type;
const char* type_cstr = type.AsCString();
diff --git a/include/lldb/DataFormatters/TypeCategory.h b/include/lldb/DataFormatters/TypeCategory.h
index b76d84f4772f..6461c4e97e4e 100644
--- a/include/lldb/DataFormatters/TypeCategory.h
+++ b/include/lldb/DataFormatters/TypeCategory.h
@@ -24,6 +24,8 @@ namespace lldb_private {
class TypeCategoryImpl
{
private:
+ typedef FormatNavigator<ConstString, TypeFormatImpl> ValueNavigator;
+ typedef FormatNavigator<lldb::RegularExpressionSP, TypeFormatImpl> RegexValueNavigator;
typedef FormatNavigator<ConstString, TypeSummaryImpl> SummaryNavigator;
typedef FormatNavigator<lldb::RegularExpressionSP, TypeSummaryImpl> RegexSummaryNavigator;
@@ -35,11 +37,16 @@ namespace lldb_private {
typedef FormatNavigator<ConstString, ScriptedSyntheticChildren> SynthNavigator;
typedef FormatNavigator<lldb::RegularExpressionSP, ScriptedSyntheticChildren> RegexSynthNavigator;
#endif // #ifndef LLDB_DISABLE_PYTHON
-
+
+ typedef ValueNavigator::MapType ValueMap;
+ typedef RegexValueNavigator::MapType RegexValueMap;
+
typedef SummaryNavigator::MapType SummaryMap;
typedef RegexSummaryNavigator::MapType RegexSummaryMap;
+
typedef FilterNavigator::MapType FilterMap;
typedef RegexFilterNavigator::MapType RegexFilterMap;
+
#ifndef LLDB_DISABLE_PYTHON
typedef SynthNavigator::MapType SynthMap;
typedef RegexSynthNavigator::MapType RegexSynthMap;
@@ -49,9 +56,13 @@ namespace lldb_private {
typedef uint16_t FormatCategoryItems;
static const uint16_t ALL_ITEM_TYPES = UINT16_MAX;
+
+ typedef ValueNavigator::SharedPointer ValueNavigatorSP;
+ typedef RegexValueNavigator::SharedPointer RegexValueNavigatorSP;
typedef SummaryNavigator::SharedPointer SummaryNavigatorSP;
typedef RegexSummaryNavigator::SharedPointer RegexSummaryNavigatorSP;
+
typedef FilterNavigator::SharedPointer FilterNavigatorSP;
typedef RegexFilterNavigator::SharedPointer RegexFilterNavigatorSP;
#ifndef LLDB_DISABLE_PYTHON
@@ -62,6 +73,18 @@ namespace lldb_private {
TypeCategoryImpl (IFormatChangeListener* clist,
ConstString name);
+ ValueNavigatorSP
+ GetValueNavigator ()
+ {
+ return ValueNavigatorSP(m_value_nav);
+ }
+
+ RegexValueNavigatorSP
+ GetRegexValueNavigator ()
+ {
+ return RegexValueNavigatorSP(m_regex_value_nav);
+ }
+
SummaryNavigatorSP
GetSummaryNavigator ()
{
@@ -85,6 +108,9 @@ namespace lldb_private {
{
return RegexFilterNavigatorSP(m_regex_filter_nav);
}
+
+ ValueNavigator::MapValueType
+ GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp);
SummaryNavigator::MapValueType
GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp);
@@ -98,7 +124,13 @@ namespace lldb_private {
#endif
lldb::TypeNameSpecifierImplSP
+ GetTypeNameSpecifierForFormatAtIndex (size_t index);
+
+ lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierForSummaryAtIndex (size_t index);
+
+ ValueNavigator::MapValueType
+ GetFormatAtIndex (size_t index);
SummaryNavigator::MapValueType
GetSummaryAtIndex (size_t index);
@@ -145,6 +177,13 @@ namespace lldb_private {
return m_enabled_position;
}
+
+ bool
+ Get (ValueObject& valobj,
+ lldb::TypeFormatImplSP& entry,
+ lldb::DynamicValueType use_dynamic,
+ uint32_t* reason = NULL);
+
bool
Get (ValueObject& valobj,
lldb::TypeSummaryImplSP& entry,
@@ -183,10 +222,15 @@ namespace lldb_private {
typedef std::shared_ptr<TypeCategoryImpl> SharedPointer;
private:
+ ValueNavigator::SharedPointer m_value_nav;
+ RegexValueNavigator::SharedPointer m_regex_value_nav;
+
SummaryNavigator::SharedPointer m_summary_nav;
RegexSummaryNavigator::SharedPointer m_regex_summary_nav;
+
FilterNavigator::SharedPointer m_filter_nav;
RegexFilterNavigator::SharedPointer m_regex_filter_nav;
+
#ifndef LLDB_DISABLE_PYTHON
SynthNavigator::SharedPointer m_synth_nav;
RegexSynthNavigator::SharedPointer m_regex_synth_nav;
@@ -213,6 +257,9 @@ namespace lldb_private {
friend class TypeCategoryMap;
+ friend class FormatNavigator<ConstString, TypeFormatImpl>;
+ friend class FormatNavigator<lldb::RegularExpressionSP, TypeFormatImpl>;
+
friend class FormatNavigator<ConstString, TypeSummaryImpl>;
friend class FormatNavigator<lldb::RegularExpressionSP, TypeSummaryImpl>;
diff --git a/include/lldb/DataFormatters/TypeCategoryMap.h b/include/lldb/DataFormatters/TypeCategoryMap.h
index c2465ad13aa7..6bed18719893 100644
--- a/include/lldb/DataFormatters/TypeCategoryMap.h
+++ b/include/lldb/DataFormatters/TypeCategoryMap.h
@@ -93,6 +93,10 @@ namespace lldb_private {
{
return m_map.size();
}
+
+ lldb::TypeFormatImplSP
+ GetFormat (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic);
lldb::TypeSummaryImplSP
GetSummaryFormat (ValueObject& valobj,
diff --git a/include/lldb/DataFormatters/TypeSummary.h b/include/lldb/DataFormatters/TypeSummary.h
index 2183384b9d62..1c195ab2ba4d 100644
--- a/include/lldb/DataFormatters/TypeSummary.h
+++ b/include/lldb/DataFormatters/TypeSummary.h
@@ -12,7 +12,6 @@
// C Includes
#include <stdint.h>
-#include <unistd.h>
// C++ Includes
#include <string>
@@ -239,7 +238,7 @@ namespace lldb_private {
}
bool
- IsOneliner () const
+ IsOneLiner () const
{
return m_flags.GetShowMembersOneLiner();
}
@@ -281,7 +280,7 @@ namespace lldb_private {
}
void
- SetIsOneliner (bool value)
+ SetIsOneLiner (bool value)
{
m_flags.SetShowMembersOneLiner(value);
}
diff --git a/include/lldb/DataFormatters/TypeSynthetic.h b/include/lldb/DataFormatters/TypeSynthetic.h
index a32f4b761175..18b9d011e96a 100644
--- a/include/lldb/DataFormatters/TypeSynthetic.h
+++ b/include/lldb/DataFormatters/TypeSynthetic.h
@@ -12,7 +12,6 @@
// C Includes
#include <stdint.h>
-#include <unistd.h>
// C++ Includes
#include <string>
@@ -533,6 +532,12 @@ namespace lldb_private {
FrontEnd (std::string pclass,
ValueObject &backend);
+ bool
+ IsValid ()
+ {
+ return m_wrapper_sp.get() != nullptr && m_wrapper_sp->operator bool() && m_interpreter != nullptr;
+ }
+
virtual
~FrontEnd ();
@@ -582,8 +587,11 @@ namespace lldb_private {
virtual SyntheticChildrenFrontEnd::AutoPointer
GetFrontEnd(ValueObject &backend)
{
- return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend));
- }
+ auto synth_ptr = SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend));
+ if (synth_ptr && ((FrontEnd*)synth_ptr.get())->IsValid())
+ return synth_ptr;
+ return NULL;
+ }
private:
DISALLOW_COPY_AND_ASSIGN(ScriptedSyntheticChildren);
diff --git a/include/lldb/DataFormatters/ValueObjectPrinter.h b/include/lldb/DataFormatters/ValueObjectPrinter.h
new file mode 100644
index 000000000000..4e23ceedcc16
--- /dev/null
+++ b/include/lldb/DataFormatters/ValueObjectPrinter.h
@@ -0,0 +1,394 @@
+//===-- ValueObjectPrinter.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_ValueObjectPrinter_h_
+#define lldb_ValueObjectPrinter_h_
+
+// C Includes
+// C++ Includes
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/lldb-public.h"
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+
+namespace lldb_private {
+
+struct DumpValueObjectOptions
+{
+ uint32_t m_max_ptr_depth;
+ uint32_t m_max_depth;
+ bool m_show_types;
+ bool m_show_location;
+ bool m_use_objc;
+ lldb::DynamicValueType m_use_dynamic;
+ bool m_use_synthetic;
+ bool m_scope_already_checked;
+ bool m_flat_output;
+ uint32_t m_omit_summary_depth;
+ bool m_ignore_cap;
+ lldb::Format m_format;
+ lldb::TypeSummaryImplSP m_summary_sp;
+ std::string m_root_valobj_name;
+ bool m_hide_root_type;
+ bool m_hide_name;
+ bool m_hide_value;
+ bool m_be_raw;
+
+ DumpValueObjectOptions() :
+ m_max_ptr_depth(0),
+ m_max_depth(UINT32_MAX),
+ m_show_types(false),
+ m_show_location(false),
+ m_use_objc(false),
+ m_use_dynamic(lldb::eNoDynamicValues),
+ m_use_synthetic(true),
+ m_scope_already_checked(false),
+ m_flat_output(false),
+ m_omit_summary_depth(0),
+ m_ignore_cap(false),
+ m_format (lldb::eFormatDefault),
+ m_summary_sp(),
+ m_root_valobj_name(),
+ m_hide_root_type(false), // provide a special compact display for "po"
+ m_hide_name(false), // provide a special compact display for "po"
+ m_hide_value(false), // provide a special compact display for "po"
+ m_be_raw(false)
+ {}
+
+ static const DumpValueObjectOptions
+ DefaultOptions()
+ {
+ static DumpValueObjectOptions g_default_options;
+
+ return g_default_options;
+ }
+
+ DumpValueObjectOptions (const DumpValueObjectOptions& rhs) :
+ m_max_ptr_depth(rhs.m_max_ptr_depth),
+ m_max_depth(rhs.m_max_depth),
+ m_show_types(rhs.m_show_types),
+ m_show_location(rhs.m_show_location),
+ m_use_objc(rhs.m_use_objc),
+ m_use_dynamic(rhs.m_use_dynamic),
+ m_use_synthetic(rhs.m_use_synthetic),
+ m_scope_already_checked(rhs.m_scope_already_checked),
+ m_flat_output(rhs.m_flat_output),
+ m_omit_summary_depth(rhs.m_omit_summary_depth),
+ m_ignore_cap(rhs.m_ignore_cap),
+ m_format(rhs.m_format),
+ m_summary_sp(rhs.m_summary_sp),
+ m_root_valobj_name(rhs.m_root_valobj_name),
+ m_hide_root_type(rhs.m_hide_root_type),
+ m_hide_name(rhs.m_hide_name),
+ m_hide_value(rhs.m_hide_value),
+ m_be_raw(rhs.m_be_raw)
+ {}
+
+ DumpValueObjectOptions&
+ SetMaximumPointerDepth(uint32_t depth = 0)
+ {
+ m_max_ptr_depth = depth;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetMaximumDepth(uint32_t depth = 0)
+ {
+ m_max_depth = depth;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetShowTypes(bool show = false)
+ {
+ m_show_types = show;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetShowLocation(bool show = false)
+ {
+ m_show_location = show;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetUseObjectiveC(bool use = false)
+ {
+ m_use_objc = use;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetShowSummary(bool show = true)
+ {
+ if (show == false)
+ SetOmitSummaryDepth(UINT32_MAX);
+ else
+ SetOmitSummaryDepth(0);
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetUseDynamicType(lldb::DynamicValueType dyn = lldb::eNoDynamicValues)
+ {
+ m_use_dynamic = dyn;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetUseSyntheticValue(bool use_synthetic = true)
+ {
+ m_use_synthetic = use_synthetic;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetScopeChecked(bool check = true)
+ {
+ m_scope_already_checked = check;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetFlatOutput(bool flat = false)
+ {
+ m_flat_output = flat;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetOmitSummaryDepth(uint32_t depth = 0)
+ {
+ m_omit_summary_depth = depth;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetIgnoreCap(bool ignore = false)
+ {
+ m_ignore_cap = ignore;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetRawDisplay(bool raw = false)
+ {
+ if (raw)
+ {
+ SetUseSyntheticValue(false);
+ SetOmitSummaryDepth(UINT32_MAX);
+ SetIgnoreCap(true);
+ SetHideName(false);
+ SetHideValue(false);
+ m_be_raw = true;
+ }
+ else
+ {
+ SetUseSyntheticValue(true);
+ SetOmitSummaryDepth(0);
+ SetIgnoreCap(false);
+ SetHideName(false);
+ SetHideValue(false);
+ m_be_raw = false;
+ }
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetFormat (lldb::Format format = lldb::eFormatDefault)
+ {
+ m_format = format;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetSummary (lldb::TypeSummaryImplSP summary = lldb::TypeSummaryImplSP())
+ {
+ m_summary_sp = summary;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetRootValueObjectName (const char* name = NULL)
+ {
+ if (name)
+ m_root_valobj_name.assign(name);
+ else
+ m_root_valobj_name.clear();
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetHideRootType (bool hide_root_type = false)
+ {
+ m_hide_root_type = hide_root_type;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetHideName (bool hide_name = false)
+ {
+ m_hide_name = hide_name;
+ return *this;
+ }
+
+ DumpValueObjectOptions&
+ SetHideValue (bool hide_value = false)
+ {
+ m_hide_value = hide_value;
+ return *this;
+ }
+};
+
+class ValueObjectPrinter
+{
+public:
+
+ ValueObjectPrinter (ValueObject* valobj,
+ Stream* s,
+ const DumpValueObjectOptions& options);
+
+ ~ValueObjectPrinter () {}
+
+ bool
+ PrintValueObject ();
+
+ bool
+ PrintChildrenOneLiner (bool hide_names);
+
+protected:
+
+ // only this class (and subclasses, if any) should ever be concerned with
+ // the depth mechanism
+ ValueObjectPrinter (ValueObject* valobj,
+ Stream* s,
+ const DumpValueObjectOptions& options,
+ uint32_t ptr_depth,
+ uint32_t curr_depth);
+
+ // we should actually be using delegating constructors here
+ // but some versions of GCC still have trouble with those
+ void
+ Init (ValueObject* valobj,
+ Stream* s,
+ const DumpValueObjectOptions& options,
+ uint32_t ptr_depth,
+ uint32_t curr_depth);
+
+ bool
+ GetDynamicValueIfNeeded ();
+
+ const char*
+ GetDescriptionForDisplay ();
+
+ const char*
+ GetRootNameForDisplay (const char* if_fail = nullptr);
+
+ bool
+ ShouldPrintValueObject ();
+
+ bool
+ IsNil ();
+
+ bool
+ IsPtr ();
+
+ bool
+ IsRef ();
+
+ bool
+ IsAggregate ();
+
+ bool
+ PrintLocationIfNeeded ();
+
+ bool
+ PrintTypeIfNeeded ();
+
+ bool
+ PrintNameIfNeeded (bool show_type);
+
+ bool
+ CheckScopeIfNeeded ();
+
+ TypeSummaryImpl*
+ GetSummaryFormatter ();
+
+ void
+ GetValueSummaryError (std::string& value,
+ std::string& summary,
+ std::string& error);
+
+ bool
+ PrintValueAndSummaryIfNeeded (bool& value_printed,
+ bool& summary_printed);
+
+ bool
+ PrintObjectDescriptionIfNeeded (bool value_printed,
+ bool summary_printed);
+
+ bool
+ ShouldPrintChildren (bool is_failed_description,
+ uint32_t& curr_ptr_depth);
+
+ ValueObject*
+ GetValueObjectForChildrenGeneration ();
+
+ void
+ PrintChildrenPreamble ();
+
+ void
+ PrintChildrenPostamble (bool print_dotdotdot);
+
+ void
+ PrintChild (lldb::ValueObjectSP child_sp,
+ uint32_t curr_ptr_depth);
+
+ uint32_t
+ GetMaxNumChildrenToPrint (bool& print_dotdotdot);
+
+ void
+ PrintChildren (uint32_t curr_ptr_depth);
+
+ void
+ PrintChildrenIfNeeded (bool value_printed,
+ bool summary_printed);
+
+private:
+
+ ValueObject *m_orig_valobj;
+ ValueObject *m_valobj;
+ Stream *m_stream;
+ DumpValueObjectOptions options;
+ Flags m_type_flags;
+ ClangASTType m_clang_type;
+ uint32_t m_ptr_depth;
+ uint32_t m_curr_depth;
+ LazyBool m_should_print;
+ LazyBool m_is_nil;
+ LazyBool m_is_ptr;
+ LazyBool m_is_ref;
+ LazyBool m_is_aggregate;
+ std::pair<TypeSummaryImpl*,bool> m_summary_formatter;
+ std::string m_value;
+ std::string m_summary;
+ std::string m_error;
+
+ DISALLOW_COPY_AND_ASSIGN(ValueObjectPrinter);
+};
+
+} // namespace lldb_private
+
+#endif // lldb_ValueObjectPrinter_h_
diff --git a/include/lldb/Expression/ClangExpressionDeclMap.h b/include/lldb/Expression/ClangExpressionDeclMap.h
index b2a43e0ac75f..b04e1bd6f116 100644
--- a/include/lldb/Expression/ClangExpressionDeclMap.h
+++ b/include/lldb/Expression/ClangExpressionDeclMap.h
@@ -291,6 +291,9 @@ public:
/// @param[in] name
/// The name of the symbol.
///
+ /// @param[in] module
+ /// The module to limit the search to. This can be NULL
+ ///
/// @return
/// Valid load address for the symbol
//------------------------------------------------------------------
@@ -298,7 +301,8 @@ public:
GetSymbolAddress (Target &target,
Process *process,
const ConstString &name,
- lldb::SymbolType symbol_type);
+ lldb::SymbolType symbol_type,
+ Module *module = NULL);
lldb::addr_t
GetSymbolAddress (const ConstString &name,
@@ -504,12 +508,16 @@ private:
/// @param[in] name
/// The name as a plain C string.
///
+ /// @param[in] module
+ /// The module to limit the search to. This can be NULL
+ ///
/// @return
/// The LLDB Symbol found, or NULL if none was found.
- //---------------------------------------------------------
+ //------------------------------------------------------------------
const Symbol *
FindGlobalDataSymbol (Target &target,
- const ConstString &name);
+ const ConstString &name,
+ Module *module = NULL);
//------------------------------------------------------------------
/// Given a target, find a variable that matches the given name and
diff --git a/include/lldb/Expression/ClangFunction.h b/include/lldb/Expression/ClangFunction.h
index 3f96f7bd3117..9cb22ed15cb5 100644
--- a/include/lldb/Expression/ClangFunction.h
+++ b/include/lldb/Expression/ClangFunction.h
@@ -67,8 +67,8 @@ class ClangFunction : public ClangExpression
{
friend class ASTStructExtractor;
public:
- //------------------------------------------------------------------
- /// Constructor
+ //------------------------------------------------------------------
+ /// Constructor
///
/// @param[in] exe_scope
/// An execution context scope that gets us at least a target and
@@ -84,14 +84,14 @@ public:
/// @param[in] arg_value_list
/// The default values to use when calling this function. Can
/// be overridden using WriteFunctionArguments().
- //------------------------------------------------------------------
- ClangFunction (ExecutionContextScope &exe_scope,
+ //------------------------------------------------------------------
+ ClangFunction (ExecutionContextScope &exe_scope,
Function &function_ptr,
ClangASTContext *ast_context,
const ValueList &arg_value_list);
//------------------------------------------------------------------
- /// Constructor
+ /// Constructor
///
/// @param[in] exe_scope
/// An execution context scope that gets us at least a target and
@@ -110,32 +110,32 @@ public:
/// @param[in] arg_value_list
/// The default values to use when calling this function. Can
/// be overridden using WriteFunctionArguments().
- //------------------------------------------------------------------
- ClangFunction (ExecutionContextScope &exe_scope,
+ //------------------------------------------------------------------
+ ClangFunction (ExecutionContextScope &exe_scope,
const ClangASTType &return_type,
const Address& function_address,
const ValueList &arg_value_list);
//------------------------------------------------------------------
- /// Destructor
- //------------------------------------------------------------------
- virtual
+ /// Destructor
+ //------------------------------------------------------------------
+ virtual
~ClangFunction();
//------------------------------------------------------------------
- /// Compile the wrapper function
+ /// Compile the wrapper function
///
/// @param[in] errors
/// The stream to print parser errors to.
///
/// @return
/// The number of errors.
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
unsigned
CompileFunction (Stream &errors);
//------------------------------------------------------------------
- /// Insert the default function wrapper and its default argument struct
+ /// Insert the default function wrapper and its default argument struct
///
/// @param[in] exe_ctx
/// The execution context to insert the function and its arguments
@@ -151,14 +151,14 @@ public:
///
/// @return
/// True on success; false otherwise.
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
bool
InsertFunction (ExecutionContext &exe_ctx,
lldb::addr_t &args_addr_ref,
Stream &errors);
//------------------------------------------------------------------
- /// Insert the default function wrapper (using the JIT)
+ /// Insert the default function wrapper (using the JIT)
///
/// @param[in] exe_ctx
/// The execution context to insert the function and its arguments
@@ -169,12 +169,12 @@ public:
///
/// @return
/// True on success; false otherwise.
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
bool WriteFunctionWrapper (ExecutionContext &exe_ctx,
Stream &errors);
//------------------------------------------------------------------
- /// Insert the default function argument struct
+ /// Insert the default function argument struct
///
/// @param[in] exe_ctx
/// The execution context to insert the function and its arguments
@@ -190,13 +190,13 @@ public:
///
/// @return
/// True on success; false otherwise.
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
bool WriteFunctionArguments (ExecutionContext &exe_ctx,
lldb::addr_t &args_addr_ref,
Stream &errors);
//------------------------------------------------------------------
- /// Insert an argument struct with a non-default function address and
+ /// Insert an argument struct with a non-default function address and
/// non-default argument values
///
/// @param[in] exe_ctx
@@ -219,7 +219,7 @@ public:
///
/// @return
/// True on success; false otherwise.
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
bool WriteFunctionArguments (ExecutionContext &exe_ctx,
lldb::addr_t &args_addr_ref,
Address function_address,
@@ -227,7 +227,7 @@ public:
Stream &errors);
//------------------------------------------------------------------
- /// [Static] Execute a function, passing it a single void* parameter.
+ /// [Static] Execute a function, passing it a single void* parameter.
/// ClangFunction uses this to call the wrapper function.
///
/// @param[in] exe_ctx
@@ -266,7 +266,7 @@ public:
///
/// @return
/// Returns one of the ExecutionResults enum indicating function call status.
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
static ExecutionResults
ExecuteFunction (ExecutionContext &exe_ctx,
lldb::addr_t function_address,
@@ -446,7 +446,7 @@ public:
///
/// @return
/// A ThreadPlan for executing the function.
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
static ThreadPlan *
GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::addr_t func_addr,
@@ -482,7 +482,7 @@ public:
///
/// @return
/// A ThreadPlan for executing the function.
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
ThreadPlan *
GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::addr_t &args_addr_ref,
@@ -514,7 +514,7 @@ public:
///
/// @return
/// True on success; false otherwise.
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
bool FetchFunctionResults (ExecutionContext &exe_ctx,
lldb::addr_t args_addr,
Value &ret_value);
@@ -528,7 +528,7 @@ public:
///
/// @param[in] args_addr
/// The address of the argument struct.
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
void DeallocateFunctionResults (ExecutionContext &exe_ctx,
lldb::addr_t args_addr);
@@ -614,9 +614,9 @@ public:
return m_arg_values;
}
private:
- //------------------------------------------------------------------
- // For ClangFunction only
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
+ // For ClangFunction only
+ //------------------------------------------------------------------
std::unique_ptr<ClangExpressionParser> m_parser; ///< The parser responsible for compiling the function.
std::unique_ptr<IRExecutionUnit> m_execution_unit_ap;
@@ -624,17 +624,18 @@ private:
Function *m_function_ptr; ///< The function we're going to call. May be NULL if we don't have debug info for the function.
Address m_function_addr; ///< If we don't have the FunctionSP, we at least need the address & return type.
ClangASTType m_function_return_type; ///< The opaque clang qual type for the function return type.
- ClangASTContext *m_clang_ast_context; ///< This is the clang_ast_context that we're getting types from the and value, and the function return the function pointer is NULL.
std::string m_wrapper_function_name; ///< The name of the wrapper function.
std::string m_wrapper_function_text; ///< The contents of the wrapper function.
std::string m_wrapper_struct_name; ///< The name of the struct that contains the target function address, arguments, and result.
std::list<lldb::addr_t> m_wrapper_args_addrs; ///< The addresses of the arguments to the wrapper function.
+ std::unique_ptr<ASTStructExtractor> m_struct_extractor; ///< The class that generates the argument struct below.
+
bool m_struct_valid; ///< True if the ASTStructExtractor has populated the variables below.
- //------------------------------------------------------------------
- /// These values are populated by the ASTStructExtractor
+ //------------------------------------------------------------------
+ /// These values are populated by the ASTStructExtractor
size_t m_struct_size; ///< The size of the argument struct, in bytes.
std::vector<uint64_t> m_member_offsets; ///< The offset of each member in the struct, in bytes.
uint64_t m_return_size; ///< The size of the result variable, in bytes.
diff --git a/include/lldb/Expression/ClangUserExpression.h b/include/lldb/Expression/ClangUserExpression.h
index 47bfebb46648..b8c3c128acf4 100644
--- a/include/lldb/Expression/ClangUserExpression.h
+++ b/include/lldb/Expression/ClangUserExpression.h
@@ -126,13 +126,8 @@ public:
/// The execution context to use when looking up entities that
/// are needed for parsing (locations of variables, etc.)
///
- /// @param[in] unwind_on_error
- /// If true, and the execution stops before completion, we unwind the
- /// function call, and return the program state to what it was before the
- /// execution. If false, we leave the program in the stopped state.
- ///
- /// @param[in] ignore_breakpoints
- /// If true, ignore breakpoints while executing the expression.
+ /// @param[in] options
+ /// Expression evaluation options.
///
/// @param[in] shared_ptr_to_me
/// This is a shared pointer to this ClangUserExpression. This is
@@ -145,29 +140,15 @@ public:
/// A pointer to direct at the persistent variable in which the
/// expression's result is stored.
///
- /// @param[in] try_all_threads
- /// If true, then we will try to run all threads if the function doesn't complete on
- /// one thread. See timeout_usec for the interaction of this variable and
- /// the timeout.
- ///
- /// @param[in] timeout_usec
- /// Timeout value (0 for no timeout). If try_all_threads is true, then we
- /// will try on one thread for the lesser of .25 sec and half the total timeout.
- /// then switch to running all threads, otherwise this will be the total timeout.
- ///
- ///
/// @return
/// A Process::Execution results value.
//------------------------------------------------------------------
ExecutionResults
Execute (Stream &error_stream,
ExecutionContext &exe_ctx,
- bool unwind_on_error,
- bool ignore_breakpoints,
+ const EvaluateExpressionOptions& options,
ClangUserExpressionSP &shared_ptr_to_me,
- lldb::ClangExpressionVariableSP &result,
- bool try_all_threads,
- uint32_t timeout_usec);
+ lldb::ClangExpressionVariableSP &result);
ThreadPlan *
GetThreadPlanToExecuteJITExpression (Stream &error_stream,
@@ -300,25 +281,8 @@ public:
/// @param[in] exe_ctx
/// The execution context to use when evaluating the expression.
///
- /// @param[in] execution_policy
- /// Determines whether or not to try using the IR interpreter to
- /// avoid running the expression on the parser.
- ///
- /// @param[in] language
- /// If not eLanguageTypeUnknown, a language to use when parsing
- /// the expression. Currently restricted to those languages
- /// supported by Clang.
- ///
- /// @param[in] unwind_on_error
- /// True if the thread's state should be restored in the case
- /// of an error.
- ///
- /// @param[in] ignore_breakpoints
- /// If true, ignore breakpoints while executing the expression.
- ///
- /// @param[in] result_type
- /// If not eResultTypeAny, the type of the desired result. Will
- /// result in parse errors if impossible.
+ /// @param[in] options
+ /// Expression evaluation options.
///
/// @param[in] expr_cstr
/// A C string containing the expression to be evaluated.
@@ -330,45 +294,20 @@ public:
/// @param[in/out] result_valobj_sp
/// If execution is successful, the result valobj is placed here.
///
- /// @param[in] try_all_threads
- /// If true, then we will try to run all threads if the function doesn't complete on
- /// one thread. See timeout_usec for the interaction of this variable and
- /// the timeout.
- ///
- /// @param[in] timeout_usec
- /// Timeout value (0 for no timeout). If try_all_threads is true, then we
- /// will try on one thread for the lesser of .25 sec and half the total timeout.
- /// then switch to running all threads, otherwise this will be the total timeout.
+ /// @param[out]
+ /// Filled in with an error in case the expression evaluation
+ /// fails to parse, run, or evaluated.
///
/// @result
/// A Process::ExecutionResults value. eExecutionCompleted for success.
//------------------------------------------------------------------
static ExecutionResults
Evaluate (ExecutionContext &exe_ctx,
- lldb_private::ExecutionPolicy execution_policy,
- lldb::LanguageType language,
- ResultType desired_type,
- bool unwind_on_error,
- bool ignore_breakpoints,
+ const EvaluateExpressionOptions& options,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp,
- bool try_all_threads,
- uint32_t timeout_usec);
-
- static ExecutionResults
- EvaluateWithError (ExecutionContext &exe_ctx,
- lldb_private::ExecutionPolicy execution_policy,
- lldb::LanguageType language,
- ResultType desired_type,
- bool unwind_on_error,
- bool ignore_breakpoints,
- const char *expr_cstr,
- const char *expr_prefix,
- lldb::ValueObjectSP &result_valobj_sp,
- Error &error,
- bool try_all_threads,
- uint32_t timeout_usec);
+ Error &error);
static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression.
private:
diff --git a/include/lldb/Expression/DWARFExpression.h b/include/lldb/Expression/DWARFExpression.h
index 2692831ecc84..5ecdf7fe9ee5 100644
--- a/include/lldb/Expression/DWARFExpression.h
+++ b/include/lldb/Expression/DWARFExpression.h
@@ -58,7 +58,8 @@ public:
/// @param[in] data_length
/// The byte length of the location expression.
//------------------------------------------------------------------
- DWARFExpression(const DataExtractor& data,
+ DWARFExpression(lldb::ModuleSP module,
+ const DataExtractor& data,
lldb::offset_t data_offset,
lldb::offset_t data_length);
@@ -172,6 +173,9 @@ public:
/// Make the expression parser read its location information from a
/// given data source
///
+ /// @param[in] module_sp
+ /// The module that defines the DWARF expression.
+ ///
/// @param[in] data
/// A data extractor configured to read the DWARF location expression's
/// bytecode.
@@ -183,7 +187,7 @@ public:
/// The byte length of the location expression.
//------------------------------------------------------------------
void
- SetOpcodeData(const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length);
+ SetOpcodeData(lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length);
//------------------------------------------------------------------
/// Copy the DWARF location expression into a local buffer.
@@ -199,6 +203,9 @@ public:
/// the data, it shouldn't amount to that much for the variables we
/// end up parsing.
///
+ /// @param[in] module_sp
+ /// The module that defines the DWARF expression.
+ ///
/// @param[in] data
/// A data extractor configured to read and copy the DWARF
/// location expression's bytecode.
@@ -210,7 +217,8 @@ public:
/// The byte length of the location expression.
//------------------------------------------------------------------
void
- CopyOpcodeData (const DataExtractor& data,
+ CopyOpcodeData (lldb::ModuleSP module_sp,
+ const DataExtractor& data,
lldb::offset_t data_offset,
lldb::offset_t data_length);
@@ -279,6 +287,9 @@ public:
/// expression. The location expression may access the target's
/// memory, especially if it comes from the expression parser.
///
+ /// @param[in] opcode_ctx
+ /// The module which defined the expression.
+ ///
/// @param[in] opcodes
/// This is a static method so the opcodes need to be provided
/// explicitly.
@@ -332,6 +343,7 @@ public:
ClangExpressionVariableList *expr_locals,
ClangExpressionDeclMap *decl_map,
RegisterContext *reg_ctx,
+ lldb::ModuleSP opcode_ctx,
const DataExtractor& opcodes,
const lldb::offset_t offset,
const lldb::offset_t length,
@@ -410,7 +422,8 @@ protected:
//------------------------------------------------------------------
/// Classes that inherit from DWARFExpression can see and modify these
//------------------------------------------------------------------
-
+
+ lldb::ModuleWP m_module_wp; ///< Module which defined this expression.
DataExtractor m_data; ///< A data extractor capable of reading opcode bytes
lldb::RegisterKind m_reg_kind; ///< One of the defines that starts with LLDB_REGKIND_
lldb::addr_t m_loclist_slide; ///< A value used to slide the location list offsets so that
diff --git a/include/lldb/Expression/IRExecutionUnit.h b/include/lldb/Expression/IRExecutionUnit.h
index 885b6516b0c6..2820317e108e 100644
--- a/include/lldb/Expression/IRExecutionUnit.h
+++ b/include/lldb/Expression/IRExecutionUnit.h
@@ -287,7 +287,8 @@ private:
/// Allocated space.
//------------------------------------------------------------------
virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID);
+ unsigned SectionID,
+ llvm::StringRef SectionName);
//------------------------------------------------------------------
/// Allocate space for data, and add it to the m_spaceBlocks map
@@ -308,7 +309,9 @@ private:
/// Allocated space.
//------------------------------------------------------------------
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID, bool IsReadOnly);
+ unsigned SectionID,
+ llvm::StringRef SectionName,
+ bool IsReadOnly);
//------------------------------------------------------------------
/// Allocate space for a global variable, and add it to the
@@ -388,6 +391,10 @@ private:
return m_default_mm_ap->GetNumStubSlabs();
}
+ virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
+ return m_default_mm_ap->registerEHFrames(Addr, LoadAddr, Size);
+ }
+
//------------------------------------------------------------------
/// Passthrough interface stub
//------------------------------------------------------------------
diff --git a/include/lldb/Expression/IRForTarget.h b/include/lldb/Expression/IRForTarget.h
index 151bf2ab4774..566328772502 100644
--- a/include/lldb/Expression/IRForTarget.h
+++ b/include/lldb/Expression/IRForTarget.h
@@ -19,6 +19,7 @@
#include "llvm/Pass.h"
#include <map>
+#include <functional>
namespace llvm {
class BasicBlock;
diff --git a/include/lldb/Host/Condition.h b/include/lldb/Host/Condition.h
index 98439ee2ebdf..2f1858b75a56 100644
--- a/include/lldb/Host/Condition.h
+++ b/include/lldb/Host/Condition.h
@@ -12,7 +12,7 @@
#if defined(__cplusplus)
-#include <pthread.h>
+#include "lldb/lldb-types.h"
#include "lldb/Host/Mutex.h"
namespace lldb_private {
@@ -105,7 +105,7 @@ protected:
//------------------------------------------------------------------
// Member variables
//------------------------------------------------------------------
- pthread_cond_t m_condition; ///< The condition variable.
+ lldb::condition_t m_condition; ///< The condition variable.
//------------------------------------------------------------------
/// Get accessor to the pthread condition object.
@@ -113,7 +113,7 @@ protected:
/// @return
/// A pointer to the condition variable owned by this object.
//------------------------------------------------------------------
- pthread_cond_t *
+ lldb::condition_t *
GetCondition ();
};
diff --git a/include/lldb/Host/Config.h b/include/lldb/Host/Config.h
index 2d5d39baac3d..80616b747cf5 100644
--- a/include/lldb/Host/Config.h
+++ b/include/lldb/Host/Config.h
@@ -14,7 +14,7 @@
#include "lldb/Host/macosx/Config.h"
-#elif defined(__linux__)
+#elif defined(__linux__) || defined(__GNU__)
#include "lldb/Host/linux/Config.h"
@@ -26,6 +26,10 @@
#include "lldb/Host/mingw/Config.h"
+#elif defined(_MSC_VER)
+
+#include "lldb/Host/msvc/Config.h"
+
#else
#error undefined platform
diff --git a/include/lldb/Host/File.h b/include/lldb/Host/File.h
index df7fe92cccba..7ca582402b32 100644
--- a/include/lldb/Host/File.h
+++ b/include/lldb/Host/File.h
@@ -11,7 +11,9 @@
#define liblldb_File_h_
#if defined(__cplusplus)
+#include <stdarg.h>
#include <stdio.h>
+#include <sys/types.h>
#include "lldb/lldb-private.h"
@@ -41,17 +43,20 @@ public:
eOpenOptionCanCreateNewOnly = (1u << 6) // Can create file only if it doesn't already exist
};
+ static mode_t
+ ConvertOpenOptionsForPOSIXOpen (uint32_t open_options);
+
enum Permissions
{
- ePermissionsUserRead = (1u << 0),
- ePermissionsUserWrite = (1u << 1),
- ePermissionsUserExecute = (1u << 2),
- ePermissionsGroupRead = (1u << 3),
+ ePermissionsUserRead = (1u << 8),
+ ePermissionsUserWrite = (1u << 7),
+ ePermissionsUserExecute = (1u << 6),
+ ePermissionsGroupRead = (1u << 5),
ePermissionsGroupWrite = (1u << 4),
- ePermissionsGroupExecute = (1u << 5),
- ePermissionsWorldRead = (1u << 6),
- ePermissionsWorldWrite = (1u << 7),
- ePermissionsWorldExecute = (1u << 8),
+ ePermissionsGroupExecute = (1u << 3),
+ ePermissionsWorldRead = (1u << 2),
+ ePermissionsWorldWrite = (1u << 1),
+ ePermissionsWorldExecute = (1u << 0),
ePermissionsUserRW = (ePermissionsUserRead | ePermissionsUserWrite | 0 ),
ePermissionsUserRX = (ePermissionsUserRead | 0 | ePermissionsUserExecute ),
@@ -117,6 +122,27 @@ public:
uint32_t options,
uint32_t permissions = ePermissionsDefault);
+ //------------------------------------------------------------------
+ /// Constructor with FileSpec.
+ ///
+ /// Takes a FileSpec pointing to a file which can be just a filename, or a full
+ /// path. If \a path is not NULL or empty, this function will call
+ /// File::Open (const char *path, uint32_t options, uint32_t permissions).
+ ///
+ /// @param[in] path
+ /// The FileSpec for this file.
+ ///
+ /// @param[in] options
+ /// Options to use when opening (see File::OpenOptions)
+ ///
+ /// @param[in] permissions
+ /// Options to use when opening (see File::Permissions)
+ ///
+ /// @see File::Open (const char *path, uint32_t options, uint32_t permissions)
+ //------------------------------------------------------------------
+ File (const FileSpec& filespec,
+ uint32_t options,
+ uint32_t permissions = ePermissionsDefault);
File (int fd, bool tranfer_ownership) :
m_descriptor (fd),
@@ -451,6 +477,19 @@ public:
//------------------------------------------------------------------
Error
Sync ();
+
+ //------------------------------------------------------------------
+ /// Get the permissions for a this file.
+ ///
+ /// @return
+ /// Bits logical OR'ed together from the permission bits defined
+ /// in lldb_private::File::Permissions.
+ //------------------------------------------------------------------
+ uint32_t
+ GetPermissions(Error &error) const;
+
+ static uint32_t
+ GetPermissions (const char *path, Error &error);
//------------------------------------------------------------------
/// Output printf formatted output to the stream.
diff --git a/include/lldb/Host/FileSpec.h b/include/lldb/Host/FileSpec.h
index c58be9ec09d5..dfc6b711ae4a 100644
--- a/include/lldb/Host/FileSpec.h
+++ b/include/lldb/Host/FileSpec.h
@@ -177,7 +177,7 @@ public:
/// A pointer to this object if either the directory or filename
/// is valid, NULL otherwise.
//------------------------------------------------------------------
- operator bool() const;
+ explicit operator bool() const;
//------------------------------------------------------------------
/// Logical NOT operator.
@@ -624,6 +624,21 @@ public:
static size_t
Resolve (const char *src_path, char *dst_path, size_t dst_len);
+ FileSpec
+ CopyByAppendingPathComponent (const char *new_path) const;
+
+ FileSpec
+ CopyByRemovingLastPathComponent () const;
+
+ void
+ AppendPathComponent (const char *new_path);
+
+ void
+ RemoveLastPathComponent ();
+
+ const char*
+ GetLastPathComponent () const;
+
//------------------------------------------------------------------
/// Resolves the user name at the beginning of \a src_path, and writes the output
/// to \a dst_path. Note, \a src_path can contain other path components after the
diff --git a/include/lldb/Host/Host.h b/include/lldb/Host/Host.h
index 547bdd5d637b..1d667dee5a20 100644
--- a/include/lldb/Host/Host.h
+++ b/include/lldb/Host/Host.h
@@ -18,6 +18,7 @@
#include "lldb/lldb-private.h"
#include "lldb/Core/StringList.h"
+#include "lldb/Host/File.h"
namespace lldb_private {
@@ -209,6 +210,9 @@ public:
static lldb::pid_t
GetCurrentProcessID ();
+ static void
+ Kill(lldb::pid_t pid, int signo);
+
//------------------------------------------------------------------
/// Get the thread ID for the calling thread in the current process.
///
@@ -264,6 +268,17 @@ public:
lldb::thread_result_t *thread_result_ptr,
Error *error);
+ typedef void (*ThreadLocalStorageCleanupCallback) (void *p);
+
+ static lldb::thread_key_t
+ ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback);
+
+ static void*
+ ThreadLocalStorageGet(lldb::thread_key_t key);
+
+ static void
+ ThreadLocalStorageSet(lldb::thread_key_t key, void *value);
+
//------------------------------------------------------------------
/// Gets the name of a thread in a process.
///
@@ -458,7 +473,7 @@ public:
int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
std::string *command_output, // Pass NULL if you don't want the command output
uint32_t timeout_sec,
- const char *shell = "/bin/bash");
+ const char *shell = LLDB_DEFAULT_SHELL);
static lldb::DataBufferSP
GetAuxvData (lldb_private::Process *process);
@@ -494,6 +509,45 @@ public:
DynamicLibraryGetSymbol (void *dynamic_library_handle,
const char *symbol_name,
Error &error);
+
+ static uint32_t
+ MakeDirectory (const char* path, mode_t mode);
+
+ static lldb::user_id_t
+ OpenFile (const FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ Error &error);
+
+ static bool
+ CloseFile (lldb::user_id_t fd,
+ Error &error);
+
+ static uint64_t
+ WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ Error &error);
+
+ static uint64_t
+ ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void* dst,
+ uint64_t dst_len,
+ Error &error);
+
+ static lldb::user_id_t
+ GetFileSize (const FileSpec& file_spec);
+
+ static bool
+ GetFileExists (const FileSpec& file_spec);
+
+ static bool
+ CalculateMD5 (const FileSpec& file_spec,
+ uint64_t &low,
+ uint64_t &high);
+
};
} // namespace lldb_private
diff --git a/include/lldb/Host/Mutex.h b/include/lldb/Host/Mutex.h
index 63f759efe366..496dd0496c13 100644
--- a/include/lldb/Host/Mutex.h
+++ b/include/lldb/Host/Mutex.h
@@ -11,7 +11,7 @@
#define liblldb_Mutex_h_
#if defined(__cplusplus)
-#include <pthread.h>
+#include "lldb/lldb-types.h"
#include <assert.h>
#ifdef LLDB_CONFIGURATION_DEBUG
@@ -238,7 +238,7 @@ protected:
//------------------------------------------------------------------
// TODO: Hide the mutex in the implementation file in case we ever need to port to an
// architecture that doesn't have pthread mutexes.
- pthread_mutex_t m_mutex; ///< The pthread mutex object.
+ lldb::mutex_t m_mutex; ///< The OS mutex object.
private:
//------------------------------------------------------------------
@@ -247,7 +247,7 @@ private:
/// @return
/// A pointer to the pthread mutex object owned by this object.
//------------------------------------------------------------------
- pthread_mutex_t *
+ lldb::mutex_t *
GetMutex();
Mutex(const Mutex&);
diff --git a/include/lldb/Host/OptionParser.h b/include/lldb/Host/OptionParser.h
new file mode 100644
index 000000000000..410e4d9f9468
--- /dev/null
+++ b/include/lldb/Host/OptionParser.h
@@ -0,0 +1,53 @@
+//===-- OptionParser.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_OptionParser_h_
+#define liblldb_OptionParser_h_
+
+namespace lldb_private {
+
+typedef struct Option
+{
+ // name of long option
+ const char *name;
+ // one of no_argument, required_argument, and optional_argument:
+ // whether option takes an argument
+ int has_arg;
+ // if not NULL, set *flag to val when option found
+ int *flag;
+ // if flag not NULL, value to set *flag to; else return value
+ int val;
+} Option;
+
+class OptionParser
+{
+public:
+ enum OptionArgument
+ {
+ eNoArgument = 0,
+ eRequiredArgument,
+ eOptionalArgument
+ };
+
+ static void Prepare();
+
+ static void EnableError(bool error);
+
+ static int Parse(int argc, char * const argv [],
+ const char *optstring,
+ const Option *longopts, int *longindex);
+
+ static char* GetOptionArgument();
+ static int GetOptionIndex();
+ static int GetOptionErrorCause();
+};
+
+}
+
+#endif // liblldb_OptionParser_h_
diff --git a/include/lldb/Host/ProcessRunLock.h b/include/lldb/Host/ProcessRunLock.h
index f563be73fce0..eca1ad375fc6 100644
--- a/include/lldb/Host/ProcessRunLock.h
+++ b/include/lldb/Host/ProcessRunLock.h
@@ -11,9 +11,9 @@
#define liblldb_ProcessRunLock_h_
#if defined(__cplusplus)
+#include "lldb/lldb-defines.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Host/Condition.h"
-#include <pthread.h>
#include <stdint.h>
#include <time.h>
@@ -32,75 +32,14 @@ namespace lldb_private {
class ProcessRunLock
{
public:
- ProcessRunLock () :
- m_rwlock(),
- m_running(false)
- {
- int err = ::pthread_rwlock_init(&m_rwlock, NULL); (void)err;
-//#if LLDB_CONFIGURATION_DEBUG
-// assert(err == 0);
-//#endif
- }
-
- ~ProcessRunLock ()
- {
- int err = ::pthread_rwlock_destroy (&m_rwlock); (void)err;
-//#if LLDB_CONFIGURATION_DEBUG
-// assert(err == 0);
-//#endif
- }
-
- bool
- ReadTryLock ()
- {
- ::pthread_rwlock_rdlock (&m_rwlock);
- if (m_running == false)
- {
- return true;
- }
- ::pthread_rwlock_unlock (&m_rwlock);
- return false;
- }
-
- bool
- ReadUnlock ()
- {
- return ::pthread_rwlock_unlock (&m_rwlock) == 0;
- }
-
- bool
- SetRunning()
- {
- ::pthread_rwlock_wrlock (&m_rwlock);
- m_running = true;
- ::pthread_rwlock_unlock (&m_rwlock);
- return true;
- }
-
- bool
- TrySetRunning()
- {
- bool r;
-
- if (::pthread_rwlock_trywrlock (&m_rwlock) == 0)
- {
- r = !m_running;
- m_running = true;
- ::pthread_rwlock_unlock (&m_rwlock);
- return r;
- }
- return false;
- }
-
- bool
- SetStopped ()
- {
- ::pthread_rwlock_wrlock (&m_rwlock);
- m_running = false;
- ::pthread_rwlock_unlock (&m_rwlock);
- return true;
- }
-
+ ProcessRunLock();
+ ~ProcessRunLock();
+ bool ReadTryLock ();
+ bool ReadUnlock ();
+ bool SetRunning ();
+ bool TrySetRunning ();
+ bool SetStopped ();
+public:
class ProcessRunLocker
{
public:
@@ -153,7 +92,7 @@ public:
};
protected:
- pthread_rwlock_t m_rwlock;
+ lldb::rwlock_t m_rwlock;
bool m_running;
private:
DISALLOW_COPY_AND_ASSIGN(ProcessRunLock);
diff --git a/include/lldb/Host/SocketAddress.h b/include/lldb/Host/SocketAddress.h
index e63b238c7994..5e79e94fa9ec 100644
--- a/include/lldb/Host/SocketAddress.h
+++ b/include/lldb/Host/SocketAddress.h
@@ -12,9 +12,18 @@
// C Includes
#include <stdint.h>
+
+#ifdef _WIN32
+#include "lldb/Host/windows/windows.h"
+#include <winsock2.h>
+#include <WS2tcpip.h>
+typedef ADDRESS_FAMILY sa_family_t;
+typedef USHORT in_port_t;
+#else
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
+#endif
#if defined(__FreeBSD__)
#include <sys/types.h>
diff --git a/include/lldb/Host/Symbols.h b/include/lldb/Host/Symbols.h
index 9db68e1ecf15..652a614e6355 100644
--- a/include/lldb/Host/Symbols.h
+++ b/include/lldb/Host/Symbols.h
@@ -12,7 +12,6 @@
// C Includes
#include <stdint.h>
-#include <sys/time.h>
// C++ Includes
// Other libraries and framework includes
diff --git a/include/lldb/Host/Terminal.h b/include/lldb/Host/Terminal.h
index b334717c796b..5ea88c515637 100644
--- a/include/lldb/Host/Terminal.h
+++ b/include/lldb/Host/Terminal.h
@@ -12,6 +12,7 @@
#if defined(__cplusplus)
#include "lldb/lldb-private.h"
+#include "lldb/Host/Config.h"
struct termios;
@@ -173,7 +174,9 @@ protected:
//------------------------------------------------------------------
Terminal m_tty; ///< A terminal
int m_tflags; ///< Cached tflags information.
+#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
std::unique_ptr<struct termios> m_termios_ap; ///< Cached terminal state information.
+#endif
lldb::pid_t m_process_group;///< Cached process group information.
};
diff --git a/include/lldb/Host/TimeValue.h b/include/lldb/Host/TimeValue.h
index 8c43d6d0e5ff..ba230045307f 100644
--- a/include/lldb/Host/TimeValue.h
+++ b/include/lldb/Host/TimeValue.h
@@ -12,6 +12,7 @@
// C Includes
#include <stdint.h>
+#ifndef _MSC_VER
#include <sys/time.h>
// BEGIN: MinGW work around
@@ -19,6 +20,7 @@
#include <pthread.h>
#endif
// END: MinGW work around
+#endif
// C++ Includes
// Other libraries and framework includes
@@ -40,7 +42,7 @@ public:
TimeValue();
TimeValue(const TimeValue& rhs);
TimeValue(const struct timespec& ts);
- TimeValue(const struct timeval& tv);
+ explicit TimeValue(uint32_t seconds, uint32_t nanos = 0);
~TimeValue();
//------------------------------------------------------------------
@@ -64,9 +66,6 @@ public:
struct timespec
GetAsTimeSpec () const;
- struct timeval
- GetAsTimeVal () const;
-
bool
IsValid () const;
@@ -85,6 +84,23 @@ public:
void
Dump (Stream *s, uint32_t width = 0) const;
+ /// Returns only the seconds component of the TimeValue. The nanoseconds
+ /// portion is ignored. No rounding is performed.
+ /// @brief Retrieve the seconds component
+ uint32_t seconds() const { return m_nano_seconds / NanoSecPerSec; }
+
+ /// Returns only the nanoseconds component of the TimeValue. The seconds
+ /// portion is ignored.
+ /// @brief Retrieve the nanoseconds component.
+ uint32_t nanoseconds() const { return m_nano_seconds % NanoSecPerSec; }
+
+ /// Returns only the fractional portion of the TimeValue rounded down to the
+ /// nearest microsecond (divide by one thousand).
+ /// @brief Retrieve the fractional part as microseconds;
+ uint32_t microseconds() const {
+ return (m_nano_seconds % NanoSecPerSec) / NanoSecPerMicroSec;
+ }
+
protected:
//------------------------------------------------------------------
// Classes that inherit from TimeValue can see and modify these
diff --git a/include/lldb/Interpreter/Args.h b/include/lldb/Interpreter/Args.h
index d06c3e56aecd..27feca63e4ad 100644
--- a/include/lldb/Interpreter/Args.h
+++ b/include/lldb/Interpreter/Args.h
@@ -11,8 +11,6 @@
#define liblldb_Command_h_
// C Includes
-#include <getopt.h>
-
// C++ Includes
#include <list>
#include <string>
@@ -24,6 +22,7 @@
#include "lldb/lldb-private-types.h"
#include "lldb/lldb-types.h"
#include "lldb/Core/Error.h"
+#include "lldb/Host/OptionParser.h"
namespace lldb_private {
@@ -319,7 +318,7 @@ public:
ParseOptions (Options &options);
size_t
- FindArgumentIndexForOption (struct option *long_options, int long_options_index);
+ FindArgumentIndexForOption (Option *long_options, int long_options_index);
bool
IsPositionalArgument (const char *arg);
diff --git a/include/lldb/Interpreter/CommandObject.h b/include/lldb/Interpreter/CommandObject.h
index 2bfab0a8ecc4..8544fd9f9c3f 100644
--- a/include/lldb/Interpreter/CommandObject.h
+++ b/include/lldb/Interpreter/CommandObject.h
@@ -42,7 +42,7 @@ public:
return (*help_callback)();
}
- operator bool() const
+ explicit operator bool() const
{
return (help_callback != NULL);
}
diff --git a/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h b/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
index da05e127d5d1..c09528f9f514 100644
--- a/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
+++ b/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
@@ -62,8 +62,8 @@ public:
ignore_cap == true;
}
- ValueObject::DumpValueObjectOptions
- GetAsDumpOptions (bool objc_is_compact = false,
+ DumpValueObjectOptions
+ GetAsDumpOptions (LanguageRuntimeDescriptionDisplayVerbosity lang_descr_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull,
lldb::Format format = lldb::eFormatDefault,
lldb::TypeSummaryImplSP summary_sp = lldb::TypeSummaryImplSP());
diff --git a/include/lldb/Interpreter/OptionValueBoolean.h b/include/lldb/Interpreter/OptionValueBoolean.h
index 2b935e9e03e6..e024f3a0f3db 100644
--- a/include/lldb/Interpreter/OptionValueBoolean.h
+++ b/include/lldb/Interpreter/OptionValueBoolean.h
@@ -92,7 +92,7 @@ public:
/// /b True this object contains a valid namespace decl, \b
/// false otherwise.
//------------------------------------------------------------------
- operator bool() const
+ explicit operator bool() const
{
return m_current_value;
}
diff --git a/include/lldb/Interpreter/OptionValueEnumeration.h b/include/lldb/Interpreter/OptionValueEnumeration.h
index 012eeb68ac0e..68beddfce0d0 100644
--- a/include/lldb/Interpreter/OptionValueEnumeration.h
+++ b/include/lldb/Interpreter/OptionValueEnumeration.h
@@ -34,7 +34,7 @@ public:
const char *description;
};
typedef UniqueCStringMap<EnumeratorInfo> EnumerationMap;
- typedef typename EnumerationMap::Entry EnumerationMapEntry;
+ typedef EnumerationMap::Entry EnumerationMapEntry;
OptionValueEnumeration (const OptionEnumValueElement *enumerators, enum_type value);
diff --git a/include/lldb/Interpreter/Options.h b/include/lldb/Interpreter/Options.h
index ac4daa8f579a..2b4ac1190557 100644
--- a/include/lldb/Interpreter/Options.h
+++ b/include/lldb/Interpreter/Options.h
@@ -11,7 +11,6 @@
#define liblldb_Options_h_
// C Includes
-#include <getopt.h>
// C++ Includes
#include <set>
@@ -141,7 +140,7 @@ public:
/// @see Args::ParseOptions (Options&)
/// @see man getopt_long_only
//------------------------------------------------------------------
- struct option *
+ Option *
GetLongOptions ();
// This gets passed the short option as an integer...
@@ -309,7 +308,7 @@ protected:
typedef std::vector<OptionSet> OptionSetVector;
CommandInterpreter &m_interpreter;
- std::vector<struct option> m_getopt_table;
+ std::vector<Option> m_getopt_table;
OptionSet m_seen_options;
OptionSetVector m_required_options;
OptionSetVector m_optional_options;
@@ -448,6 +447,12 @@ protected:
void
Finalize ();
+ bool
+ DidFinalize ()
+ {
+ return m_did_finalize;
+ }
+
virtual Error
SetOptionValue (uint32_t option_idx,
const char *option_arg);
@@ -464,6 +469,10 @@ protected:
assert (m_did_finalize);
return &m_option_defs[0];
}
+
+ const OptionGroup*
+ GetGroupWithOption (char short_opt);
+
struct OptionInfo
{
OptionInfo (OptionGroup* g, uint32_t i) :
diff --git a/include/lldb/Interpreter/PythonDataObjects.h b/include/lldb/Interpreter/PythonDataObjects.h
index b2c9240db09f..a54318159d14 100644
--- a/include/lldb/Interpreter/PythonDataObjects.h
+++ b/include/lldb/Interpreter/PythonDataObjects.h
@@ -105,7 +105,7 @@ namespace lldb_private {
PythonString
Str ();
- operator bool () const
+ explicit operator bool () const
{
return m_py_obj != NULL;
}
diff --git a/include/lldb/Interpreter/ScriptInterpreter.h b/include/lldb/Interpreter/ScriptInterpreter.h
index 9a66c775d47a..9f529b822910 100644
--- a/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/include/lldb/Interpreter/ScriptInterpreter.h
@@ -41,7 +41,7 @@ public:
return m_object;
}
- operator bool ()
+ explicit operator bool ()
{
return m_object != NULL;
}
@@ -108,44 +108,47 @@ public:
const char *session_dictionary_name,
const lldb::ProcessSP& process_sp);
- typedef uint32_t (*SWIGPythonCalculateNumChildren) (void *implementor);
- typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx);
- typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name);
- typedef void* (*SWIGPythonCastPyObjectToSBValue) (void* data);
- typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data);
- typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data);
-
-
- typedef bool (*SWIGPythonCallCommand) (const char *python_function_name,
- const char *session_dictionary_name,
- lldb::DebuggerSP& debugger,
- const char* args,
- lldb_private::CommandReturnObject& cmd_retobj);
-
- typedef bool (*SWIGPythonCallModuleInit) (const char *python_module_name,
- const char *session_dictionary_name,
- lldb::DebuggerSP& debugger);
-
- typedef bool (*SWIGPythonScriptKeyword_Process) (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::ProcessSP& process,
- std::string& output);
- typedef bool (*SWIGPythonScriptKeyword_Thread) (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::ThreadSP& thread,
- std::string& output);
-
- typedef bool (*SWIGPythonScriptKeyword_Target) (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::TargetSP& target,
- std::string& output);
-
- typedef bool (*SWIGPythonScriptKeyword_Frame) (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::StackFrameSP& frame,
- std::string& output);
-
-
+ typedef uint32_t (*SWIGPythonCalculateNumChildren) (void *implementor);
+ typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx);
+ typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name);
+ typedef void* (*SWIGPythonCastPyObjectToSBValue) (void* data);
+ typedef lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue) (void* data);
+ typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data);
+ typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data);
+
+
+ typedef bool (*SWIGPythonCallCommand) (const char *python_function_name,
+ const char *session_dictionary_name,
+ lldb::DebuggerSP& debugger,
+ const char* args,
+ lldb_private::CommandReturnObject& cmd_retobj);
+
+ typedef bool (*SWIGPythonCallModuleInit) (const char *python_module_name,
+ const char *session_dictionary_name,
+ lldb::DebuggerSP& debugger);
+
+ typedef bool (*SWIGPythonScriptKeyword_Process) (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::ProcessSP& process,
+ std::string& output);
+ typedef bool (*SWIGPythonScriptKeyword_Thread) (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::ThreadSP& thread,
+ std::string& output);
+
+ typedef bool (*SWIGPythonScriptKeyword_Target) (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::TargetSP& target,
+ std::string& output);
+
+ typedef bool (*SWIGPythonScriptKeyword_Frame) (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::StackFrameSP& frame,
+ std::string& output);
+
+ typedef void* (*SWIGPython_GetDynamicSetting) (void* module,
+ const char* setting,
+ const lldb::TargetSP& target_sp);
typedef enum
{
@@ -162,7 +165,8 @@ public:
eScriptReturnTypeFloat,
eScriptReturnTypeDouble,
eScriptReturnTypeChar,
- eScriptReturnTypeCharStrOrNone
+ eScriptReturnTypeCharStrOrNone,
+ eScriptReturnTypeOpaqueObject
} ScriptReturnType;
ScriptInterpreter (CommandInterpreter &interpreter, lldb::ScriptLanguage script_lang);
@@ -336,6 +340,22 @@ public:
{
return lldb::ScriptInterpreterObjectSP();
}
+
+ virtual lldb::ScriptInterpreterObjectSP
+ LoadPluginModule (const FileSpec& file_spec,
+ lldb_private::Error& error)
+ {
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ virtual lldb::ScriptInterpreterObjectSP
+ GetDynamicSettings (lldb::ScriptInterpreterObjectSP plugin_module_sp,
+ Target* target,
+ const char* setting_name,
+ lldb_private::Error& error)
+ {
+ return lldb::ScriptInterpreterObjectSP();
+ }
virtual bool
GenerateFunction(const char *signature, const StringList &input)
@@ -473,7 +493,8 @@ public:
LoadScriptingModule (const char* filename,
bool can_reload,
bool init_session,
- lldb_private::Error& error)
+ lldb_private::Error& error,
+ lldb::ScriptInterpreterObjectSP* module_sp = nullptr)
{
error.SetErrorString("loading unimplemented");
return false;
@@ -501,7 +522,26 @@ public:
LanguageToString (lldb::ScriptLanguage language);
static void
- InitializeInterpreter (SWIGInitCallback python_swig_init_callback);
+ InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
+ SWIGBreakpointCallbackFunction swig_breakpoint_callback,
+ SWIGWatchpointCallbackFunction swig_watchpoint_callback,
+ SWIGPythonTypeScriptCallbackFunction swig_typescript_callback,
+ SWIGPythonCreateSyntheticProvider swig_synthetic_script,
+ SWIGPythonCalculateNumChildren swig_calc_children,
+ SWIGPythonGetChildAtIndex swig_get_child_index,
+ SWIGPythonGetIndexOfChildWithName swig_get_index_child,
+ SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue ,
+ SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
+ SWIGPythonUpdateSynthProviderInstance swig_update_provider,
+ SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
+ SWIGPythonCallCommand swig_call_command,
+ SWIGPythonCallModuleInit swig_call_module_init,
+ SWIGPythonCreateOSPlugin swig_create_os_plugin,
+ SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
+ SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
+ SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
+ SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
+ SWIGPython_GetDynamicSetting swig_plugin_get);
static void
TerminateInterpreter ();
diff --git a/include/lldb/Interpreter/ScriptInterpreterPython.h b/include/lldb/Interpreter/ScriptInterpreterPython.h
index 2616f575d20e..4b3dc61f3ee8 100644
--- a/include/lldb/Interpreter/ScriptInterpreterPython.h
+++ b/include/lldb/Interpreter/ScriptInterpreterPython.h
@@ -98,6 +98,16 @@ public:
lldb::tid_t tid,
lldb::addr_t context);
+ virtual lldb::ScriptInterpreterObjectSP
+ LoadPluginModule (const FileSpec& file_spec,
+ lldb_private::Error& error);
+
+ virtual lldb::ScriptInterpreterObjectSP
+ GetDynamicSettings (lldb::ScriptInterpreterObjectSP plugin_module_sp,
+ Target* target,
+ const char* setting_name,
+ lldb_private::Error& error);
+
virtual size_t
CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor);
@@ -200,7 +210,8 @@ public:
LoadScriptingModule (const char* filename,
bool can_reload,
bool init_session,
- lldb_private::Error& error);
+ lldb_private::Error& error,
+ lldb::ScriptInterpreterObjectSP* module_sp = nullptr);
virtual lldb::ScriptInterpreterObjectSP
MakeScriptObject (void* object);
@@ -239,7 +250,26 @@ public:
InitializePrivate ();
static void
- InitializeInterpreter (SWIGInitCallback python_swig_init_callback);
+ InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
+ SWIGBreakpointCallbackFunction swig_breakpoint_callback,
+ SWIGWatchpointCallbackFunction swig_watchpoint_callback,
+ SWIGPythonTypeScriptCallbackFunction swig_typescript_callback,
+ SWIGPythonCreateSyntheticProvider swig_synthetic_script,
+ SWIGPythonCalculateNumChildren swig_calc_children,
+ SWIGPythonGetChildAtIndex swig_get_child_index,
+ SWIGPythonGetIndexOfChildWithName swig_get_index_child,
+ SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue ,
+ SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
+ SWIGPythonUpdateSynthProviderInstance swig_update_provider,
+ SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
+ SWIGPythonCallCommand swig_call_command,
+ SWIGPythonCallModuleInit swig_call_module_init,
+ SWIGPythonCreateOSPlugin swig_create_os_plugin,
+ SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
+ SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
+ SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
+ SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
+ SWIGPython_GetDynamicSetting swig_plugin_get);
protected:
@@ -254,7 +284,7 @@ protected:
void
RestoreTerminalState ();
-
+
private:
class SynchronicityHandler
@@ -282,7 +312,7 @@ private:
Py_XINCREF(m_object);
}
- operator bool ()
+ explicit operator bool ()
{
return m_object && m_object != Py_None;
}
@@ -351,7 +381,7 @@ private:
public:
PythonInputReaderManager (ScriptInterpreterPython *interpreter);
- operator bool()
+ explicit operator bool()
{
return m_error;
}
diff --git a/include/lldb/Symbol/Block.h b/include/lldb/Symbol/Block.h
index a2d703b9069c..4a305e3cbbec 100644
--- a/include/lldb/Symbol/Block.h
+++ b/include/lldb/Symbol/Block.h
@@ -17,6 +17,7 @@
#include "lldb/Core/UserID.h"
#include "lldb/Symbol/LineEntry.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/ClangASTType.h"
namespace lldb_private {
diff --git a/include/lldb/Symbol/ClangASTImporter.h b/include/lldb/Symbol/ClangASTImporter.h
index 10df7da893a8..dc6ce6b5b95b 100644
--- a/include/lldb/Symbol/ClangASTImporter.h
+++ b/include/lldb/Symbol/ClangASTImporter.h
@@ -278,6 +278,8 @@ private:
clang::Decl *Imported (clang::Decl *from, clang::Decl *to);
+ clang::Decl *GetOriginalDecl (clang::Decl *To);
+
std::set<clang::NamedDecl *> *m_decls_to_deport;
std::set<clang::NamedDecl *> *m_decls_already_deported;
ClangASTImporter &m_master;
diff --git a/include/lldb/Symbol/ClangASTType.h b/include/lldb/Symbol/ClangASTType.h
index d9e754e8ceb9..19b5d6ec6727 100644
--- a/include/lldb/Symbol/ClangASTType.h
+++ b/include/lldb/Symbol/ClangASTType.h
@@ -98,7 +98,7 @@ public:
// Tests
//----------------------------------------------------------------------
- operator bool () const
+ explicit operator bool () const
{
return m_type != NULL && m_ast != NULL;
}
@@ -155,6 +155,12 @@ public:
bool
IsFunctionType (bool *is_variadic_ptr = NULL) const;
+ size_t
+ GetNumberOfFunctionArguments () const;
+
+ ClangASTType
+ GetFunctionArgumentAtIndex (const size_t index);
+
bool
IsVariadicFunctionType () const;
@@ -195,6 +201,9 @@ public:
IsPointerToScalarType () const;
bool
+ IsRuntimeGeneratedType () const;
+
+ bool
IsPointerType (ClangASTType *pointee_type = NULL) const;
bool
@@ -249,7 +258,7 @@ public:
ConstString
GetConstTypeName () const;
- std::string
+ ConstString
GetTypeName () const;
uint32_t
diff --git a/include/lldb/Symbol/ClangNamespaceDecl.h b/include/lldb/Symbol/ClangNamespaceDecl.h
index d10ab2a29665..13a4c0011aff 100644
--- a/include/lldb/Symbol/ClangNamespaceDecl.h
+++ b/include/lldb/Symbol/ClangNamespaceDecl.h
@@ -10,6 +10,8 @@
#ifndef liblldb_ClangNamespaceDecl_h_
#define liblldb_ClangNamespaceDecl_h_
+#include <string>
+
#include "lldb/lldb-public.h"
#include "lldb/Core/ClangForward.h"
@@ -60,7 +62,7 @@ public:
/// /b True this object contains a valid namespace decl, \b
/// false otherwise.
//------------------------------------------------------------------
- operator bool() const
+ explicit operator bool() const
{
return m_ast != NULL && m_namespace_decl != NULL;
}
diff --git a/include/lldb/Symbol/ObjectFile.h b/include/lldb/Symbol/ObjectFile.h
index 8934c31bb988..ad500f5413b8 100644
--- a/include/lldb/Symbol/ObjectFile.h
+++ b/include/lldb/Symbol/ObjectFile.h
@@ -368,6 +368,34 @@ public:
GetSymtab () = 0;
//------------------------------------------------------------------
+ /// Appends a Symbol for the specified so_addr to the symbol table.
+ ///
+ /// If verify_unique is false, the symbol table is not searched
+ /// to determine if a Symbol found at this address has already been
+ /// added to the symbol table. When verify_unique is true, this
+ /// method resolves the Symbol as the first match in the SymbolTable
+ /// and appends a Symbol only if required/found.
+ ///
+ /// @return
+ /// The resolved symbol or nullptr. Returns nullptr if a
+ /// a Symbol could not be found for the specified so_addr.
+ //------------------------------------------------------------------
+ virtual Symbol *
+ ResolveSymbolForAddress(const Address &so_addr, bool verify_unique)
+ {
+ // Typically overridden to lazily add stripped symbols recoverable from
+ // the exception handling unwind information (i.e. without parsing
+ // the entire eh_frame section.
+ //
+ // The availability of LC_FUNCTION_STARTS allows ObjectFileMachO
+ // to efficiently add stripped symbols when the symbol table is
+ // first constructed. Poorer cousins are PECoff and ELF.
+ return nullptr;
+ }
+
+ //------------------------------------------------------------------
+ /// Detect if this object file has been stripped of local symbols.
+ //------------------------------------------------------------------
/// Detect if this object file has been stripped of local symbols.
///
/// @return
@@ -478,7 +506,7 @@ public:
/// The address of any auxiliary tables, or an invalid address if this
/// object file format does not support or contain such information.
virtual lldb_private::Address
- GetImageInfoAddress () { return Address(); }
+ GetImageInfoAddress (Target *target) { return Address(); }
//------------------------------------------------------------------
/// Returns the address of the Entry Point in this object file - if
@@ -612,6 +640,72 @@ public:
}
return 0;
}
+
+ //------------------------------------------------------------------
+ /// Get the minimum OS version this object file can run on.
+ ///
+ /// Some object files have information that specifies the minimum OS
+ /// version that they can be used on.
+ ///
+ /// If \a versions is NULL, or if \a num_versions is 0, the return
+ /// value will indicate how many version numbers are available in
+ /// this object file. Then a subsequent call can be made to this
+ /// function with a value of \a versions and \a num_versions that
+ /// has enough storage to store some or all version numbers.
+ ///
+ /// @param[out] versions
+ /// A pointer to an array of uint32_t types that is \a num_versions
+ /// long. If this value is NULL, the return value will indicate
+ /// how many version numbers are required for a subsequent call
+ /// to this function so that all versions can be retrieved. If
+ /// the value is non-NULL, then at most \a num_versions of the
+ /// existing versions numbers will be filled into \a versions.
+ /// If there is no version information available, \a versions
+ /// will be filled with \a num_versions UINT32_MAX values
+ /// and zero will be returned.
+ ///
+ /// @param[in] num_versions
+ /// The maximum number of entries to fill into \a versions. If
+ /// this value is zero, then the return value will indicate
+ /// how many version numbers there are in total so another call
+ /// to this function can be make with adequate storage in
+ /// \a versions to get all of the version numbers. If \a
+ /// num_versions is less than the actual number of version
+ /// numbers in this object file, only \a num_versions will be
+ /// filled into \a versions (if \a versions is non-NULL).
+ ///
+ /// @return
+ /// This function always returns the number of version numbers
+ /// that this object file has regardless of the number of
+ /// version numbers that were copied into \a versions.
+ //------------------------------------------------------------------
+ virtual uint32_t
+ GetMinimumOSVersion (uint32_t *versions, uint32_t num_versions)
+ {
+ if (versions && num_versions)
+ {
+ for (uint32_t i=0; i<num_versions; ++i)
+ versions[i] = UINT32_MAX;
+ }
+ return 0;
+ }
+
+ //------------------------------------------------------------------
+ /// Get the SDK OS version this object file was built with.
+ ///
+ /// The versions arguments and returns values are the same as the
+ /// GetMinimumOSVersion()
+ //------------------------------------------------------------------
+ virtual uint32_t
+ GetSDKVersion (uint32_t *versions, uint32_t num_versions)
+ {
+ if (versions && num_versions)
+ {
+ for (uint32_t i=0; i<num_versions; ++i)
+ versions[i] = UINT32_MAX;
+ }
+ return 0;
+ }
//------------------------------------------------------------------
// Member Functions
diff --git a/include/lldb/Symbol/Symbol.h b/include/lldb/Symbol/Symbol.h
index 11c1cc7af9ab..75e0900ab640 100644
--- a/include/lldb/Symbol/Symbol.h
+++ b/include/lldb/Symbol/Symbol.h
@@ -122,6 +122,21 @@ public:
return m_mangled;
}
+ ConstString
+ GetReExportedSymbolName() const;
+
+ FileSpec
+ GetReExportedSymbolSharedLibrary () const;
+
+ bool
+ SetReExportedSymbolName(const ConstString &name);
+
+ bool
+ SetReExportedSymbolSharedLibrary (const FileSpec &fspec);
+
+ Symbol *
+ ResolveReExportedSymbol (Target &target);
+
uint32_t
GetSiblingIndex () const;
@@ -238,24 +253,6 @@ public:
m_size_is_sibling = b;
}
-// void
-// SetValue (Address &value)
-// {
-// m_addr_range.GetBaseAddress() = value;
-// }
-//
-// void
-// SetValue (const AddressRange &range)
-// {
-// m_addr_range = range;
-// }
-//
-// void
-// SetValue (lldb::addr_t value);
-// {
-// m_addr_range.GetBaseAddress().SetRawAddress(value);
-// }
-
// If m_type is "Code" or "Function" then this will return the prologue size
// in bytes, else it will return zero.
uint32_t
diff --git a/include/lldb/Symbol/SymbolContext.h b/include/lldb/Symbol/SymbolContext.h
index 5b12adebf5f5..a0501440f18c 100644
--- a/include/lldb/Symbol/SymbolContext.h
+++ b/include/lldb/Symbol/SymbolContext.h
@@ -16,7 +16,6 @@
#include "lldb/lldb-private.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/Mangled.h"
-#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Symbol/LineEntry.h"
namespace lldb_private {
diff --git a/include/lldb/Symbol/Symtab.h b/include/lldb/Symbol/Symtab.h
index 666c3b5686b9..5dfb1c822d51 100644
--- a/include/lldb/Symbol/Symtab.h
+++ b/include/lldb/Symbol/Symtab.h
@@ -95,6 +95,10 @@ public:
bool add_mangled,
NameToIndexMap &name_to_index_map) const;
+ ObjectFile * GetObjectFile()
+ {
+ return m_objfile;
+ }
protected:
typedef std::vector<Symbol> collection;
typedef collection::iterator iterator;
diff --git a/include/lldb/Symbol/Type.h b/include/lldb/Symbol/Type.h
index 50b22fe96b9d..920f571fa1e9 100644
--- a/include/lldb/Symbol/Type.h
+++ b/include/lldb/Symbol/Type.h
@@ -304,147 +304,236 @@ protected:
ResolveClangType (ResolveState clang_type_resolve_state);
};
+// these classes are used to back the SBType* objects
-///
-/// Sometimes you can find the name of the type corresponding to an object, but we don't have debug
-/// information for it. If that is the case, you can return one of these objects, and then if it
-/// has a full type, you can use that, but if not at least you can print the name for informational
-/// purposes.
-///
-
-class TypeAndOrName
-{
-public:
- TypeAndOrName ();
- TypeAndOrName (lldb::TypeSP &type_sp);
- TypeAndOrName (const char *type_str);
- TypeAndOrName (const TypeAndOrName &rhs);
- TypeAndOrName (ConstString &type_const_string);
+class TypePair {
+private:
+ ClangASTType clang_type;
+ lldb::TypeSP type_sp;
- TypeAndOrName &
- operator= (const TypeAndOrName &rhs);
+public:
+ TypePair () : clang_type(), type_sp() {}
+ TypePair (ClangASTType type) :
+ clang_type(type),
+ type_sp()
+ {
+ }
- bool
- operator==(const TypeAndOrName &other) const;
+ TypePair (lldb::TypeSP type) :
+ clang_type(),
+ type_sp(type)
+ {
+ clang_type = type_sp->GetClangForwardType();
+ }
bool
- operator!=(const TypeAndOrName &other) const;
-
- ConstString GetName () const;
-
- lldb::TypeSP
- GetTypeSP () const
+ IsValid () const
{
- return m_type_sp;
+ return clang_type.IsValid() || (type_sp.get() != nullptr);
}
- void
- SetName (const ConstString &type_name);
-
- void
- SetName (const char *type_name_cstr);
-
- void
- SetTypeSP (lldb::TypeSP type_sp);
-
- bool
- IsEmpty ();
+ explicit operator bool () const
+ {
+ return IsValid();
+ }
bool
- HasName ();
+ operator == (const TypePair& rhs) const
+ {
+ return clang_type == rhs.clang_type &&
+ type_sp.get() == rhs.type_sp.get();
+ }
bool
- HasTypeSP ();
+ operator != (const TypePair& rhs) const
+ {
+ return clang_type != rhs.clang_type ||
+ type_sp.get() != rhs.type_sp.get();
+ }
void
- Clear ();
+ Clear ()
+ {
+ clang_type.Clear();
+ type_sp.reset();
+ }
- operator
- bool ()
+ ConstString
+ GetName () const
{
- return !IsEmpty();
+ if (type_sp)
+ return type_sp->GetName();
+ if (clang_type)
+ return clang_type.GetTypeName();
+ return ConstString ();
}
-private:
- lldb::TypeSP m_type_sp;
- ConstString m_type_name;
-};
-
-// the two classes here are used by the public API as a backend to
-// the SBType and SBTypeList classes
+ void
+ SetType (ClangASTType type)
+ {
+ type_sp.reset();
+ clang_type = type;
+ }
-class TypeImpl
-{
-public:
+ void
+ SetType (lldb::TypeSP type)
+ {
+ type_sp = type;
+ clang_type = type_sp->GetClangForwardType();
+ }
- TypeImpl() :
- m_clang_ast_type(),
- m_type_sp()
+ lldb::TypeSP
+ GetTypeSP () const
{
+ return type_sp;
}
- TypeImpl(const TypeImpl& rhs) :
- m_clang_ast_type(rhs.m_clang_ast_type),
- m_type_sp(rhs.m_type_sp)
+ ClangASTType
+ GetClangASTType () const
{
+ return clang_type;
}
- TypeImpl(const lldb_private::ClangASTType& type);
+ ClangASTType
+ GetPointerType () const
+ {
+ if (type_sp)
+ return type_sp->GetClangLayoutType().GetPointerType();
+ return clang_type.GetPointerType();
+ }
- TypeImpl(const lldb::TypeSP& type);
+ ClangASTType
+ GetPointeeType () const
+ {
+ if (type_sp)
+ return type_sp->GetClangFullType().GetPointeeType();
+ return clang_type.GetPointeeType();
+ }
- TypeImpl&
- operator = (const TypeImpl& rhs);
+ ClangASTType
+ GetReferenceType () const
+ {
+ if (type_sp)
+ return type_sp->GetClangLayoutType().GetLValueReferenceType();
+ return clang_type.GetLValueReferenceType();
+ }
- bool
- operator == (const TypeImpl& rhs)
+ ClangASTType
+ GetDereferencedType () const
{
- return m_clang_ast_type == rhs.m_clang_ast_type && m_type_sp.get() == rhs.m_type_sp.get();
+ if (type_sp)
+ return type_sp->GetClangFullType().GetNonReferenceType();
+ return clang_type.GetNonReferenceType();
}
-
- bool
- operator != (const TypeImpl& rhs)
+
+ ClangASTType
+ GetUnqualifiedType () const
{
- return m_clang_ast_type != rhs.m_clang_ast_type || m_type_sp.get() != rhs.m_type_sp.get();
+ if (type_sp)
+ return type_sp->GetClangLayoutType().GetFullyUnqualifiedType();
+ return clang_type.GetFullyUnqualifiedType();
}
- bool
- IsValid()
+ ClangASTType
+ GetCanonicalType () const
{
- return m_type_sp.get() != NULL || m_clang_ast_type.IsValid();
+ if (type_sp)
+ return type_sp->GetClangFullType().GetCanonicalType();
+ return clang_type.GetCanonicalType();
}
- const lldb_private::ClangASTType &
- GetClangASTType() const
+ clang::ASTContext *
+ GetClangASTContext () const
{
- return m_clang_ast_type;
+ return clang_type.GetASTContext();
}
+};
- clang::ASTContext*
- GetASTContext();
+class TypeImpl
+{
+public:
+
+ TypeImpl();
+
+ ~TypeImpl () {}
+
+ TypeImpl(const TypeImpl& rhs);
+
+ TypeImpl (lldb::TypeSP type_sp);
+
+ TypeImpl (ClangASTType clang_type);
- lldb::clang_type_t
- GetOpaqueQualType();
+ TypeImpl (lldb::TypeSP type_sp, ClangASTType dynamic);
+
+ TypeImpl (ClangASTType clang_type, ClangASTType dynamic);
+
+ TypeImpl (TypePair pair, ClangASTType dynamic);
- lldb::TypeSP
- GetTypeSP ()
- {
- return m_type_sp;
- }
+ void
+ SetType (lldb::TypeSP type_sp);
+
+ void
+ SetType (ClangASTType clang_type);
+
+ void
+ SetType (lldb::TypeSP type_sp, ClangASTType dynamic);
+
+ void
+ SetType (ClangASTType clang_type, ClangASTType dynamic);
+
+ void
+ SetType (TypePair pair, ClangASTType dynamic);
+
+ TypeImpl&
+ operator = (const TypeImpl& rhs);
+
+ bool
+ operator == (const TypeImpl& rhs) const;
+
+ bool
+ operator != (const TypeImpl& rhs) const;
+
+ bool
+ IsValid() const;
+
+ explicit operator bool () const;
+
+ void Clear();
ConstString
- GetName ();
-
+ GetName () const;
+
+ TypeImpl
+ GetPointerType () const;
+
+ TypeImpl
+ GetPointeeType () const;
+
+ TypeImpl
+ GetReferenceType () const;
+
+ TypeImpl
+ GetDereferencedType () const;
+
+ TypeImpl
+ GetUnqualifiedType() const;
+
+ TypeImpl
+ GetCanonicalType() const;
+
+ ClangASTType
+ GetClangASTType (bool prefer_dynamic);
+
+ clang::ASTContext *
+ GetClangASTContext (bool prefer_dynamic);
+
bool
GetDescription (lldb_private::Stream &strm,
lldb::DescriptionLevel description_level);
- void
- SetType (const lldb::TypeSP &type_sp);
-
private:
- ClangASTType m_clang_ast_type;
- lldb::TypeSP m_type_sp;
+ TypePair m_static_type;
+ ClangASTType m_dynamic_type;
};
class TypeListImpl
@@ -590,6 +679,89 @@ protected:
};
+///
+/// Sometimes you can find the name of the type corresponding to an object, but we don't have debug
+/// information for it. If that is the case, you can return one of these objects, and then if it
+/// has a full type, you can use that, but if not at least you can print the name for informational
+/// purposes.
+///
+
+class TypeAndOrName
+{
+public:
+ TypeAndOrName ();
+ TypeAndOrName (lldb::TypeSP &type_sp);
+ TypeAndOrName (const ClangASTType &clang_type);
+ TypeAndOrName (const char *type_str);
+ TypeAndOrName (const TypeAndOrName &rhs);
+ TypeAndOrName (ConstString &type_const_string);
+
+ TypeAndOrName &
+ operator= (const TypeAndOrName &rhs);
+
+ bool
+ operator==(const TypeAndOrName &other) const;
+
+ bool
+ operator!=(const TypeAndOrName &other) const;
+
+ ConstString GetName () const;
+
+ lldb::TypeSP
+ GetTypeSP () const
+ {
+ return m_type_pair.GetTypeSP();
+ }
+
+ ClangASTType
+ GetClangASTType () const
+ {
+ return m_type_pair.GetClangASTType();
+ }
+
+ void
+ SetName (const ConstString &type_name);
+
+ void
+ SetName (const char *type_name_cstr);
+
+ void
+ SetTypeSP (lldb::TypeSP type_sp);
+
+ void
+ SetClangASTType (ClangASTType clang_type);
+
+ bool
+ IsEmpty () const;
+
+ bool
+ HasName () const;
+
+ bool
+ HasTypeSP () const;
+
+ bool
+ HasClangASTType () const;
+
+ bool
+ HasType () const
+ {
+ return HasTypeSP() || HasClangASTType();
+ }
+
+ void
+ Clear ();
+
+ explicit operator bool ()
+ {
+ return !IsEmpty();
+ }
+
+private:
+ TypePair m_type_pair;
+ ConstString m_type_name;
+};
+
} // namespace lldb_private
#endif // liblldb_Type_h_
diff --git a/include/lldb/Symbol/TypeList.h b/include/lldb/Symbol/TypeList.h
index 9c74db6bf1f4..be7d35482da0 100644
--- a/include/lldb/Symbol/TypeList.h
+++ b/include/lldb/Symbol/TypeList.h
@@ -13,6 +13,7 @@
#include "lldb/lldb-private.h"
#include "lldb/Symbol/Type.h"
#include <map>
+#include <functional>
namespace lldb_private {
diff --git a/include/lldb/Target/DynamicLoader.h b/include/lldb/Target/DynamicLoader.h
index 6b76e5891ae8..272f64f33113 100644
--- a/include/lldb/Target/DynamicLoader.h
+++ b/include/lldb/Target/DynamicLoader.h
@@ -224,6 +224,26 @@ public:
return false;
}
+ //------------------------------------------------------------------
+ /// Retrieves the per-module TLS block for a given thread.
+ ///
+ /// @param[in] module
+ /// The module to query TLS data for.
+ ///
+ /// @param[in] thread
+ /// The specific thread to query TLS data for.
+ ///
+ /// @return
+ /// If the given thread has TLS data allocated for the
+ /// module, the address of the TLS block. Otherwise
+ /// LLDB_INVALID_ADDRESS is returned.
+ //------------------------------------------------------------------
+ virtual lldb::addr_t
+ GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread)
+ {
+ return LLDB_INVALID_ADDRESS;
+ }
+
protected:
//------------------------------------------------------------------
// Member variables.
diff --git a/include/lldb/Target/ExecutionContext.h b/include/lldb/Target/ExecutionContext.h
index de5fe14934a7..4038e70b0c56 100644
--- a/include/lldb/Target/ExecutionContext.h
+++ b/include/lldb/Target/ExecutionContext.h
@@ -461,6 +461,9 @@ public:
uint32_t
GetAddressByteSize() const;
+
+ lldb::ByteOrder
+ GetByteOrder() const;
//------------------------------------------------------------------
/// Returns a pointer to the target object.
diff --git a/include/lldb/Target/Platform.h b/include/lldb/Target/Platform.h
index b0a07946e74e..93cd67d66659 100644
--- a/include/lldb/Target/Platform.h
+++ b/include/lldb/Target/Platform.h
@@ -22,6 +22,7 @@
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/PluginInterface.h"
+#include "lldb/Interpreter/Options.h"
#include "lldb/Host/Mutex.h"
namespace lldb_private {
@@ -459,6 +460,15 @@ namespace lldb_private {
virtual lldb::BreakpointSP
SetThreadCreationBreakpoint (Target &target);
+ //------------------------------------------------------------------
+ // Given a target, find the local SDK directory if one exists on the
+ // current host.
+ //------------------------------------------------------------------
+ virtual lldb_private::ConstString
+ GetSDKDirectory (lldb_private::Target &target)
+ {
+ return lldb_private::ConstString();
+ }
const std::string &
GetRemoteURL () const
@@ -542,9 +552,249 @@ namespace lldb_private {
return false;
}
+ virtual uint32_t
+ MakeDirectory (const std::string &path,
+ mode_t mode)
+ {
+ return UINT32_MAX;
+ }
+
+ // this need not be virtual: the core behavior is in
+ // MakeDirectory(std::string,mode_t)
+ uint32_t
+ MakeDirectory (const FileSpec &spec,
+ mode_t mode);
+
+ virtual lldb::user_id_t
+ OpenFile (const FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ Error &error)
+ {
+ return UINT64_MAX;
+ }
+
+ virtual bool
+ CloseFile (lldb::user_id_t fd,
+ Error &error)
+ {
+ return false;
+ }
+
+ virtual lldb::user_id_t
+ GetFileSize (const FileSpec& file_spec)
+ {
+ return UINT64_MAX;
+ }
+
+ virtual uint64_t
+ ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ Error &error)
+ {
+ error.SetErrorStringWithFormat ("Platform::ReadFile() is not supported in the %s platform", GetName().GetCString());
+ return -1;
+ }
+
+ virtual uint64_t
+ WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ Error &error)
+ {
+ error.SetErrorStringWithFormat ("Platform::ReadFile() is not supported in the %s platform", GetName().GetCString());
+ return -1;
+ }
+
+ virtual Error
+ PutFile (const FileSpec& source,
+ const FileSpec& destination,
+ uint32_t uid = UINT32_MAX,
+ uint32_t gid = UINT32_MAX);
+
virtual size_t
GetEnvironment (StringList &environment);
+ virtual Error
+ GetFile (const FileSpec& source,
+ const FileSpec& destination);
+
+ virtual bool
+ GetFileExists (const lldb_private::FileSpec& file_spec);
+
+ virtual uint32_t
+ GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ Error &error)
+ {
+ error.SetErrorStringWithFormat ("Platform::GetFilePermissions() is not supported in the %s platform", GetName().GetCString());
+ return 0;
+ }
+
+ virtual bool
+ GetSupportsRSync ()
+ {
+ return m_supports_rsync;
+ }
+
+ virtual void
+ SetSupportsRSync(bool flag)
+ {
+ m_supports_rsync = flag;
+ }
+
+ virtual const char*
+ GetRSyncOpts ()
+ {
+ return m_rsync_opts.c_str();
+ }
+
+ virtual void
+ SetRSyncOpts (const char* opts)
+ {
+ m_rsync_opts.assign(opts);
+ }
+
+ virtual const char*
+ GetRSyncPrefix ()
+ {
+ return m_rsync_prefix.c_str();
+ }
+
+ virtual void
+ SetRSyncPrefix (const char* prefix)
+ {
+ m_rsync_prefix.assign(prefix);
+ }
+
+ virtual bool
+ GetSupportsSSH ()
+ {
+ return m_supports_ssh;
+ }
+
+ virtual void
+ SetSupportsSSH(bool flag)
+ {
+ m_supports_ssh = flag;
+ }
+
+ virtual const char*
+ GetSSHOpts ()
+ {
+ return m_ssh_opts.c_str();
+ }
+
+ virtual void
+ SetSSHOpts (const char* opts)
+ {
+ m_ssh_opts.assign(opts);
+ }
+
+ virtual bool
+ GetIgnoresRemoteHostname ()
+ {
+ return m_ignores_remote_hostname;
+ }
+
+ virtual void
+ SetIgnoresRemoteHostname(bool flag)
+ {
+ m_ignores_remote_hostname = flag;
+ }
+
+ virtual lldb_private::OptionGroupOptions *
+ GetConnectionOptions (CommandInterpreter& interpreter)
+ {
+ return NULL;
+ }
+
+ virtual lldb_private::Error
+ RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
+
+ virtual void
+ SetLocalCacheDirectory (const char* local);
+
+ virtual const char*
+ GetLocalCacheDirectory ();
+
+ virtual std::string
+ GetPlatformSpecificConnectionInformation()
+ {
+ return "";
+ }
+
+ virtual bool
+ CalculateMD5 (const FileSpec& file_spec,
+ uint64_t &low,
+ uint64_t &high);
+
+ virtual int32_t
+ GetResumeCountForLaunchInfo (ProcessLaunchInfo &launch_info)
+ {
+ return 1;
+ }
+
+ //------------------------------------------------------------------
+ /// Locate a queue name given a thread's qaddr
+ ///
+ /// On a system using libdispatch ("Grand Central Dispatch") style
+ /// queues, a thread may be associated with a GCD queue or not,
+ /// and a queue may be associated with multiple threads.
+ /// The process/thread must provide a way to find the "dispatch_qaddr"
+ /// for each thread, and from that dispatch_qaddr this Platform method
+ /// will locate the queue name and provide that.
+ ///
+ /// @param[in] process
+ /// A process is required for reading memory.
+ ///
+ /// @param[in] dispatch_qaddr
+ /// The dispatch_qaddr for this thread.
+ ///
+ /// @return
+ /// The name of the queue, if there is one. An empty string
+ /// means that this thread is not associated with a dispatch
+ /// queue.
+ //------------------------------------------------------------------
+ virtual std::string
+ GetQueueNameForThreadQAddress (Process *process, lldb::addr_t dispatch_qaddr)
+ {
+ return "";
+ }
+
+ //------------------------------------------------------------------
+ /// Locate a queue ID given a thread's qaddr
+ ///
+ /// On a system using libdispatch ("Grand Central Dispatch") style
+ /// queues, a thread may be associated with a GCD queue or not,
+ /// and a queue may be associated with multiple threads.
+ /// The process/thread must provide a way to find the "dispatch_qaddr"
+ /// for each thread, and from that dispatch_qaddr this Platform method
+ /// will locate the queue ID and provide that.
+ ///
+ /// @param[in] process
+ /// A process is required for reading memory.
+ ///
+ /// @param[in] dispatch_qaddr
+ /// The dispatch_qaddr for this thread.
+ ///
+ /// @return
+ /// The queue_id for this thread, if this thread is associated
+ /// with a dispatch queue. Else LLDB_INVALID_QUEUE_ID is returned.
+ //------------------------------------------------------------------
+ virtual lldb::queue_id_t
+ GetQueueIDForThreadQAddress (Process *process, lldb::addr_t dispatch_qaddr)
+ {
+ return LLDB_INVALID_QUEUE_ID;
+ }
+
protected:
bool m_is_host;
// Set to true when we are able to actually set the OS version while
@@ -569,7 +819,14 @@ namespace lldb_private {
IDToNameMap m_gid_map;
size_t m_max_uid_name_len;
size_t m_max_gid_name_len;
-
+ bool m_supports_rsync;
+ std::string m_rsync_opts;
+ std::string m_rsync_prefix;
+ bool m_supports_ssh;
+ std::string m_ssh_opts;
+ bool m_ignores_remote_hostname;
+ std::string m_local_cache_directory;
+
const char *
GetCachedUserName (uint32_t uid)
{
@@ -750,6 +1007,110 @@ namespace lldb_private {
private:
DISALLOW_COPY_AND_ASSIGN (PlatformList);
};
+
+ class OptionGroupPlatformRSync : public lldb_private::OptionGroup
+ {
+ public:
+ OptionGroupPlatformRSync ();
+
+ virtual
+ ~OptionGroupPlatformRSync ();
+
+ virtual lldb_private::Error
+ SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value);
+
+ void
+ OptionParsingStarting (CommandInterpreter &interpreter);
+
+ const lldb_private::OptionDefinition*
+ GetDefinitions ();
+
+ virtual uint32_t
+ GetNumDefinitions ();
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb_private::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ bool m_rsync;
+ std::string m_rsync_opts;
+ std::string m_rsync_prefix;
+ bool m_ignores_remote_hostname;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OptionGroupPlatformRSync);
+ };
+
+ class OptionGroupPlatformSSH : public lldb_private::OptionGroup
+ {
+ public:
+ OptionGroupPlatformSSH ();
+
+ virtual
+ ~OptionGroupPlatformSSH ();
+
+ virtual lldb_private::Error
+ SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value);
+
+ void
+ OptionParsingStarting (CommandInterpreter &interpreter);
+
+ virtual uint32_t
+ GetNumDefinitions ();
+
+ const lldb_private::OptionDefinition*
+ GetDefinitions ();
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb_private::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ bool m_ssh;
+ std::string m_ssh_opts;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OptionGroupPlatformSSH);
+ };
+
+ class OptionGroupPlatformCaching : public lldb_private::OptionGroup
+ {
+ public:
+ OptionGroupPlatformCaching ();
+
+ virtual
+ ~OptionGroupPlatformCaching ();
+
+ virtual lldb_private::Error
+ SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value);
+
+ void
+ OptionParsingStarting (CommandInterpreter &interpreter);
+
+ virtual uint32_t
+ GetNumDefinitions ();
+
+ const lldb_private::OptionDefinition*
+ GetDefinitions ();
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb_private::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ std::string m_cache_dir;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OptionGroupPlatformCaching);
+ };
+
} // namespace lldb_private
#endif // liblldb_Platform_h_
diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h
index ef89a1eb1418..aa7b5edc5af1 100644
--- a/include/lldb/Target/Process.h
+++ b/include/lldb/Target/Process.h
@@ -10,9 +10,10 @@
#ifndef liblldb_Process_h_
#define liblldb_Process_h_
+#include "lldb/Host/Config.h"
+
// C Includes
#include <limits.h>
-#include <spawn.h>
// C++ Includes
#include <list>
@@ -239,6 +240,12 @@ public:
return m_arch;
}
+ void
+ SetArchitecture (ArchSpec arch)
+ {
+ m_arch = arch;
+ }
+
lldb::pid_t
GetProcessID () const
{
@@ -475,11 +482,13 @@ public:
bool
Open (int fd, const char *path, bool read, bool write);
+#ifndef LLDB_DISABLE_POSIX
static bool
- AddPosixSpawnFileAction (posix_spawn_file_actions_t *file_actions,
+ AddPosixSpawnFileAction (void *file_actions,
const FileAction *info,
Log *log,
Error& error);
+#endif
int
GetFD () const
@@ -777,7 +786,8 @@ public:
ConvertArgumentsForLaunchingInShell (Error &error,
bool localhost,
bool will_debug,
- bool first_arg_is_full_shell_command);
+ bool first_arg_is_full_shell_command,
+ int32_t num_resumes);
void
SetMonitorProcessCallback (Host::MonitorChildProcessCallback callback,
@@ -1358,9 +1368,7 @@ class Process :
{
friend class ThreadList;
friend class ClangFunction; // For WaitForStateChangeEventsPrivate
-friend class CommandObjectProcessLaunch;
friend class ProcessEventData;
-friend class CommandObjectBreakpointCommand;
friend class StopInfo;
public:
@@ -1749,7 +1757,7 @@ public:
error.SetErrorStringWithFormat("error: %s does not support loading core files.", GetPluginName().GetCString());
return error;
}
-
+
//------------------------------------------------------------------
/// Get the dynamic loader plug-in for this process.
///
@@ -1763,6 +1771,16 @@ public:
GetDynamicLoader ();
//------------------------------------------------------------------
+ /// Get the system runtime plug-in for this process.
+ ///
+ /// @return
+ /// Returns a pointer to the SystemRuntime plugin for this Process
+ /// if one is available. Else returns NULL.
+ //------------------------------------------------------------------
+ virtual SystemRuntime *
+ GetSystemRuntime ();
+
+ //------------------------------------------------------------------
/// Attach to an existing process using the process attach info.
///
/// This function is not meant to be overridden by Process
@@ -3308,8 +3326,11 @@ public:
lldb::StateType
GetNextEvent (lldb::EventSP &event_sp);
+ // Returns the process state when it is stopped. If specified, event_sp_ptr
+ // is set to the event which triggered the stop. If wait_always = false,
+ // and the process is already stopped, this function returns immediately.
lldb::StateType
- WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr = NULL);
+ WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr = NULL, bool wait_always = true);
lldb::StateType
WaitForStateChangedEvents (const TimeValue *timeout, lldb::EventSP &event_sp);
@@ -3656,6 +3677,7 @@ protected:
std::unique_ptr<DynamicLoader> m_dyld_ap;
std::unique_ptr<DynamicCheckerFunctions> m_dynamic_checkers_ap; ///< The functions used by the expression parser to validate data that expressions use.
std::unique_ptr<OperatingSystem> m_os_ap;
+ std::unique_ptr<SystemRuntime> m_system_runtime_ap;
UnixSignals m_unix_signals; /// This is the current signal set for this process.
lldb::ABISP m_abi_sp;
lldb::InputReaderSP m_process_input_reader;
@@ -3711,10 +3733,10 @@ protected:
void
ResumePrivateStateThread ();
- static void *
+ static lldb::thread_result_t
PrivateStateThread (void *arg);
- void *
+ lldb::thread_result_t
RunPrivateStateThread ();
void
diff --git a/include/lldb/Target/RegisterContext.h b/include/lldb/Target/RegisterContext.h
index dd0e73fc7eb3..7da462700110 100644
--- a/include/lldb/Target/RegisterContext.h
+++ b/include/lldb/Target/RegisterContext.h
@@ -123,12 +123,17 @@ public:
const RegisterInfo *
GetRegisterInfoByName (const char *reg_name, uint32_t start_idx = 0);
+ const RegisterInfo *
+ GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num);
+
uint64_t
GetPC (uint64_t fail_value = LLDB_INVALID_ADDRESS);
bool
SetPC (uint64_t pc);
+ bool SetPC (Address addr);
+
uint64_t
GetSP (uint64_t fail_value = LLDB_INVALID_ADDRESS);
diff --git a/include/lldb/Target/StackFrame.h b/include/lldb/Target/StackFrame.h
index 877bd8ce661b..e7b57cd26ac9 100644
--- a/include/lldb/Target/StackFrame.h
+++ b/include/lldb/Target/StackFrame.h
@@ -26,9 +26,21 @@
namespace lldb_private {
+/// @class StackFrame StackFrame.h "lldb/Target/StackFrame.h"
+///
+/// @brief This base class provides an interface to stack frames.
+///
+/// StackFrames may have a Canonical Frame Address (CFA) or not.
+/// A frame may have a plain pc value or it may have a pc value + stop_id
+/// to indicate a specific point in the debug session so the correct section
+/// load list is used for symbolication.
+///
+/// Local variables may be available, or not. A register context may be
+/// available, or not.
+
class StackFrame :
- public std::enable_shared_from_this<StackFrame>,
- public ExecutionContextScope
+ public ExecutionContextScope,
+ public std::enable_shared_from_this<StackFrame>
{
public:
enum ExpressionPathOption
@@ -39,14 +51,72 @@ public:
eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3),
eExpressionPathOptionsAllowDirectIVarAccess = (1u << 4)
};
+
//------------------------------------------------------------------
- // Constructors and Destructors
+ /// Construct a StackFrame object without supplying a RegisterContextSP.
+ ///
+ /// This is the one constructor that doesn't take a RegisterContext
+ /// parameter. This ctor may be called when creating a history StackFrame;
+ /// these are used if we've collected a stack trace of pc addresses at
+ /// some point in the past. We may only have pc values. We may have pc
+ /// values and the stop_id when the stack trace was recorded. We may have a
+ /// CFA, or more likely, we won't.
+ ///
+ /// @param [in] thread_sp
+ /// The Thread that this frame belongs to.
+ ///
+ /// @param [in] frame_idx
+ /// This StackFrame's frame index number in the Thread. If inlined stack
+ /// frames are being created, this may differ from the concrete_frame_idx
+ /// which is the frame index without any inlined stack frames.
+ ///
+ /// @param [in] concrete_frame_idx
+ /// The StackFrame's frame index number in the Thread without any inlined
+ /// stack frames being included in the index.
+ ///
+ /// @param [in] cfa
+ /// The Canonical Frame Address (this terminology from DWARF) for this
+ /// stack frame. The CFA for a stack frame does not change over the
+ /// span of the stack frame's existence. It is often the value of the
+ /// caller's stack pointer before the call instruction into this frame's
+ /// function. It is usually not the same as the frame pointer register's
+ /// value.
+ ///
+ /// @param [in] cfa_is_valid
+ /// A history stack frame may not have a CFA value collected. We want to
+ /// distinguish between "no CFA available" and a CFA of
+ /// LLDB_INVALID_ADDRESS.
+ ///
+ /// @param [in] pc
+ /// The current pc value of this stack frame.
+ ///
+ /// @param [in] stop_id
+ /// The stop_id which should be used when looking up symbols for the pc value,
+ /// if appropriate. This argument is ignored if stop_id_is_valid is false.
+ ///
+ /// @param [in] stop_id_is_valid
+ /// If the stop_id argument provided is not needed for this StackFrame, this
+ /// should be false. If this is a history stack frame and we know the stop_id
+ /// when the pc value was collected, that stop_id should be provided and this
+ /// will be true.
+ ///
+ /// @param [in] is_history_frame
+ /// If this is a historical stack frame -- possibly without CFA or registers or
+ /// local variables -- then this should be set to true.
+ ///
+ /// @param [in] sc_ptr
+ /// Optionally seed the StackFrame with the SymbolContext information that has
+ /// already been discovered.
//------------------------------------------------------------------
StackFrame (const lldb::ThreadSP &thread_sp,
lldb::user_id_t frame_idx,
lldb::user_id_t concrete_frame_idx,
lldb::addr_t cfa,
+ bool cfa_is_valid,
lldb::addr_t pc,
+ uint32_t stop_id,
+ bool stop_id_is_valid,
+ bool is_history_frame,
const SymbolContext *sc_ptr);
StackFrame (const lldb::ThreadSP &thread_sp,
@@ -76,21 +146,103 @@ public:
StackID&
GetStackID();
+ //------------------------------------------------------------------
+ /// Get an Address for the current pc value in this StackFrame.
+ ///
+ /// May not be the same as the actual PC value for inlined stack frames.
+ ///
+ /// @return
+ /// The Address object set to the current PC value.
+ //------------------------------------------------------------------
const Address&
GetFrameCodeAddress();
-
- void
+
+ //------------------------------------------------------------------
+ /// Change the pc value for a given thread.
+ ///
+ /// Change the current pc value for the frame on this thread.
+ ///
+ /// @param[in] pc
+ /// The load address that the pc will be set to.
+ ///
+ /// @return
+ /// true if the pc was changed. false if this failed -- possibly
+ /// because this frame is not a live StackFrame.
+ //------------------------------------------------------------------
+ bool
ChangePC (lldb::addr_t pc);
+ //------------------------------------------------------------------
+ /// Provide a SymbolContext for this StackFrame's current pc value.
+ ///
+ /// The StackFrame maintains this SymbolContext and adds additional information
+ /// to it on an as-needed basis. This helps to avoid different functions
+ /// looking up symbolic information for a given pc value multple times.
+ ///
+ /// @params [in] resolve_scope
+ /// Flags from the SymbolContextItem enumerated type which specify what
+ /// type of symbol context is needed by this caller.
+ ///
+ /// @return
+ /// A SymbolContext reference which includes the types of information
+ /// requested by resolve_scope, if they are available.
+ //------------------------------------------------------------------
const SymbolContext&
GetSymbolContext (uint32_t resolve_scope);
+ //------------------------------------------------------------------
+ /// Return the Canonical Frame Address (DWARF term) for this frame.
+ ///
+ /// The CFA is typically the value of the stack pointer register before
+ /// the call invocation is made. It will not change during the lifetime
+ /// of a stack frame. It is often not the same thing as the frame pointer
+ /// register value.
+ ///
+ /// Live StackFrames will always have a CFA but other types of frames may
+ /// not be able to supply one.
+ ///
+ /// @param [out] value
+ /// The address of the CFA for this frame, if available.
+ ///
+ /// @param [out] error_ptr
+ /// If there is an error determining the CFA address, this may contain a
+ /// string explaining the failure.
+ ///
+ /// @return
+ /// Returns true if the CFA value was successfully set in value. Some
+ /// frames may be unable to provide this value; they will return false.
+ //------------------------------------------------------------------
bool
GetFrameBaseValue(Scalar &value, Error *error_ptr);
+ //------------------------------------------------------------------
+ /// Get the current lexical scope block for this StackFrame, if possible.
+ ///
+ /// If debug information is available for this stack frame, return a
+ /// pointer to the innermost lexical Block that the frame is currently
+ /// executing.
+ ///
+ /// @return
+ /// A pointer to the current Block. NULL is returned if this can
+ /// not be provided.
+ //------------------------------------------------------------------
Block *
GetFrameBlock ();
+ //------------------------------------------------------------------
+ /// Get the RegisterContext for this frame, if possible.
+ ///
+ /// Returns a shared pointer to the RegisterContext for this stack frame.
+ /// Only a live StackFrame object will be able to return a RegisterContext -
+ /// callers must be prepared for an empty shared pointer being returned.
+ ///
+ /// Even a live StackFrame RegisterContext may not be able to provide all
+ /// registers. Only the currently executing frame (frame 0) can reliably
+ /// provide every register in the register context.
+ ///
+ /// @return
+ /// The RegisterContext shared point for this frame.
+ //------------------------------------------------------------------
lldb::RegisterContextSP
GetRegisterContext ();
@@ -100,73 +252,237 @@ public:
return m_reg_context_sp;
}
+ //------------------------------------------------------------------
+ /// Retrieve the list of variables that are in scope at this StackFrame's pc.
+ ///
+ /// A frame that is not live may return an empty VariableList for a given
+ /// pc value even though variables would be available at this point if
+ /// it were a live stack frame.
+ ///
+ /// @param[in] get_file_globals
+ /// Whether to also retrieve compilation-unit scoped variables
+ /// that are visisble to the entire compilation unit (e.g. file
+ /// static in C, globals that are homed in this CU).
+ ///
+ /// @return
+ /// A pointer to a list of variables.
+ //------------------------------------------------------------------
VariableList *
GetVariableList (bool get_file_globals);
+ //------------------------------------------------------------------
+ /// Retrieve the list of variables that are in scope at this StackFrame's pc.
+ ///
+ /// A frame that is not live may return an empty VariableListSP for a
+ /// given pc value even though variables would be available at this point
+ /// if it were a live stack frame.
+ ///
+ /// @param[in] get_file_globals
+ /// Whether to also retrieve compilation-unit scoped variables
+ /// that are visisble to the entire compilation unit (e.g. file
+ /// static in C, globals that are homed in this CU).
+ ///
+ /// @return
+ /// A pointer to a list of variables.
+ //------------------------------------------------------------------
lldb::VariableListSP
GetInScopeVariableList (bool get_file_globals);
- // See ExpressionPathOption enumeration for "options" values
+ //------------------------------------------------------------------
+ /// Create a ValueObject for a variable name / pathname, possibly
+ /// including simple dereference/child selection syntax.
+ ///
+ /// @param[in] var_expr
+ /// The string specifying a variable to base the VariableObject off
+ /// of.
+ ///
+ /// @param[in] use_dynamic
+ /// Whether the correct dynamic type of an object pointer should be
+ /// determined before creating the object, or if the static type is
+ /// sufficient. One of the DynamicValueType enumerated values.
+ ///
+ /// @param[in] options
+ /// An unsigned integer of flags, values from StackFrame::ExpressionPathOption
+ /// enum.
+ /// @param[in] var_sp
+ /// A VariableSP that will be set to the variable described in the
+ /// var_expr path.
+ ///
+ /// @param[in] error
+ /// Record any errors encountered while evaluating var_expr.
+ ///
+ /// @return
+ /// A shared pointer to the ValueObject described by var_expr.
+ //------------------------------------------------------------------
lldb::ValueObjectSP
- GetValueForVariableExpressionPath (const char *var_expr,
- lldb::DynamicValueType use_dynamic,
+ GetValueForVariableExpressionPath (const char *var_expr,
+ lldb::DynamicValueType use_dynamic,
uint32_t options,
lldb::VariableSP &var_sp,
Error &error);
+ //------------------------------------------------------------------
+ /// Determine whether this StackFrame has debug information available or not
+ ///
+ /// @return
+ // true if debug information is available for this frame (function,
+ // compilation unit, block, etc.)
+ //------------------------------------------------------------------
bool
HasDebugInformation ();
+ //------------------------------------------------------------------
+ /// Return the disassembly for the instructions of this StackFrame's function
+ /// as a single C string.
+ ///
+ /// @return
+ // C string with the assembly instructions for this function.
+ //------------------------------------------------------------------
const char *
Disassemble ();
+ //------------------------------------------------------------------
+ /// Print a description for this frame using the frame-format formatter settings.
+ ///
+ /// @param [in] strm
+ /// The Stream to print the description to.
+ ///
+ /// @param [in] frame_marker
+ /// Optional string that will be prepended to the frame output description.
+ //------------------------------------------------------------------
void
- DumpUsingSettingsFormat (Stream *strm);
-
+ DumpUsingSettingsFormat (Stream *strm, const char *frame_marker = NULL);
+
+ //------------------------------------------------------------------
+ /// Print a description for this frame using a default format.
+ ///
+ /// @param [in] strm
+ /// The Stream to print the description to.
+ ///
+ /// @param [in] show_frame_index
+ /// Whether to print the frame number or not.
+ ///
+ /// @param [in] show_fullpaths
+ /// Whether to print the full source paths or just the file base name.
+ //------------------------------------------------------------------
void
Dump (Stream *strm, bool show_frame_index, bool show_fullpaths);
-
+
+ //------------------------------------------------------------------
+ /// Print a description of this stack frame and/or the source context/assembly
+ /// for this stack frame.
+ ///
+ /// @param[in] strm
+ /// The Stream to send the output to.
+ ///
+ /// @param[in] show_frame_info
+ /// If true, print the frame info by calling DumpUsingSettingsFormat().
+ ///
+ /// @param[in] show_source
+ /// If true, print source or disassembly as per the user's settings.
+ ///
+ /// @param[in] frame_marker
+ /// Passed to DumpUsingSettingsFormat() for the frame info printing.
+ ///
+ /// @return
+ /// Returns true if successful.
+ //------------------------------------------------------------------
+ bool
+ GetStatus (Stream &strm,
+ bool show_frame_info,
+ bool show_source,
+ const char *frame_marker = NULL);
+
+ //------------------------------------------------------------------
+ /// Query whether this frame is a concrete frame on the call stack,
+ /// or if it is an inlined frame derived from the debug information
+ /// and presented by the debugger.
+ ///
+ /// @return
+ /// true if this is an inlined frame.
+ //------------------------------------------------------------------
bool
IsInlined ();
+ //------------------------------------------------------------------
+ /// Query this frame to find what frame it is in this Thread's StackFrameList.
+ ///
+ /// @return
+ /// StackFrame index 0 indicates the currently-executing function. Inline
+ /// frames are included in this frame index count.
+ //------------------------------------------------------------------
uint32_t
GetFrameIndex () const;
+ //------------------------------------------------------------------
+ /// Query this frame to find what frame it is in this Thread's StackFrameList,
+ /// not counting inlined frames.
+ ///
+ /// @return
+ /// StackFrame index 0 indicates the currently-executing function. Inline
+ /// frames are not included in this frame index count; their concrete
+ /// frame index will be the same as the concrete frame that they are
+ /// derived from.
+ //------------------------------------------------------------------
uint32_t
GetConcreteFrameIndex () const
{
return m_concrete_frame_index;
}
-
+
+ //------------------------------------------------------------------
+ /// Create a ValueObject for a given Variable in this StackFrame.
+ ///
+ /// @params [in] variable_sp
+ /// The Variable to base this ValueObject on
+ ///
+ /// @params [in] use_dynamic
+ /// Whether the correct dynamic type of the variable should be
+ /// determined before creating the ValueObject, or if the static type
+ /// is sufficient. One of the DynamicValueType enumerated values.
+ ///
+ /// @return
+ // A ValueObject for this variable.
+ //------------------------------------------------------------------
lldb::ValueObjectSP
GetValueObjectForFrameVariable (const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic);
+ //------------------------------------------------------------------
+ /// Add an arbitrary Variable object (e.g. one that specifics a global or static)
+ /// to a StackFrame's list of ValueObjects.
+ ///
+ /// @params [in] variable_sp
+ /// The Variable to base this ValueObject on
+ ///
+ /// @params [in] use_dynamic
+ /// Whether the correct dynamic type of the variable should be
+ /// determined before creating the ValueObject, or if the static type
+ /// is sufficient. One of the DynamicValueType enumerated values.
+ ///
+ /// @return
+ // A ValueObject for this variable.
+ //------------------------------------------------------------------
lldb::ValueObjectSP
TrackGlobalVariable (const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic);
-
+
//------------------------------------------------------------------
// lldb::ExecutionContextScope pure virtual functions
//------------------------------------------------------------------
virtual lldb::TargetSP
CalculateTarget ();
-
+
virtual lldb::ProcessSP
CalculateProcess ();
-
+
virtual lldb::ThreadSP
CalculateThread ();
-
+
virtual lldb::StackFrameSP
CalculateStackFrame ();
- virtual void
+ void
CalculateExecutionContext (ExecutionContext &exe_ctx);
-
- bool
- GetStatus (Stream &strm,
- bool show_frame_info,
- bool show_source);
-
+
protected:
friend class StackFrameList;
@@ -175,7 +491,7 @@ protected:
void
UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame);
-
+
void
UpdatePreviousFrameFromCurrentFrame (StackFrame &curr_frame);
@@ -196,6 +512,10 @@ private:
Flags m_flags;
Scalar m_frame_base;
Error m_frame_base_error;
+ bool m_cfa_is_valid; // Does this frame have a CFA? Different from CFA == LLDB_INVALID_ADDRESS
+ uint32_t m_stop_id;
+ bool m_stop_id_is_valid; // Does this frame have a stop_id? Use it when referring to the m_frame_code_addr.
+ bool m_is_history_frame;
lldb::VariableListSP m_variable_list_sp;
ValueObjectList m_variable_list_value_objects; // Value objects for each variable in m_variable_list_sp
StreamString m_disassembly;
diff --git a/include/lldb/Target/StackFrameList.h b/include/lldb/Target/StackFrameList.h
index b2689d0391e9..2680be3e5a68 100644
--- a/include/lldb/Target/StackFrameList.h
+++ b/include/lldb/Target/StackFrameList.h
@@ -88,7 +88,8 @@ public:
uint32_t first_frame,
uint32_t num_frames,
bool show_frame_info,
- uint32_t num_frames_with_source);
+ uint32_t num_frames_with_source,
+ const char *frame_marker = NULL);
protected:
diff --git a/include/lldb/Target/StackID.h b/include/lldb/Target/StackID.h
index 7e713c73d972..75ad8ab38903 100644
--- a/include/lldb/Target/StackID.h
+++ b/include/lldb/Target/StackID.h
@@ -110,13 +110,18 @@ public:
protected:
friend class StackFrame;
-
+
void
SetPC (lldb::addr_t pc)
{
m_pc = pc;
}
+ void
+ SetCFA (lldb::addr_t cfa)
+ {
+ m_cfa = cfa;
+ }
//------------------------------------------------------------------
// Classes that inherit from StackID can see and modify these
diff --git a/include/lldb/Target/SystemRuntime.h b/include/lldb/Target/SystemRuntime.h
new file mode 100644
index 000000000000..6c0a4205d5f2
--- /dev/null
+++ b/include/lldb/Target/SystemRuntime.h
@@ -0,0 +1,174 @@
+//===-- SystemRuntime.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_SystemRuntime_h_
+#define liblldb_SystemRuntime_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include <vector>
+
+#include "lldb/lldb-public.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/lldb-private.h"
+
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class SystemRuntime SystemRuntime.h "lldb/Target/SystemRuntime.h"
+/// @brief A plug-in interface definition class for system runtimes.
+///
+/// The system runtime plugins can collect information from the system
+/// libraries during a Process' lifetime and provide information about
+/// how objects/threads were originated.
+///
+/// For instance, a system runtime plugin use a breakpoint when threads
+/// are created to record the backtrace of where that thread was created.
+/// Later, when backtracing the created thread, it could extend the backtrace
+/// to show where it was originally created from.
+///
+/// The plugin will insert its own breakpoint when Created and start collecting
+/// information. Later when it comes time to augment a Thread, it can be
+/// asked to provide that information.
+///
+//----------------------------------------------------------------------
+
+class SystemRuntime :
+ public PluginInterface
+{
+public:
+ //------------------------------------------------------------------
+ /// Find a system runtime plugin for a given process.
+ ///
+ /// Scans the installed SystemRuntime plugins and tries to find
+ /// an instance that can be used to track image changes in \a
+ /// process.
+ ///
+ /// @param[in] process
+ /// The process for which to try and locate a system runtime
+ /// plugin instance.
+ //------------------------------------------------------------------
+ static SystemRuntime*
+ FindPlugin (Process *process);
+
+ //------------------------------------------------------------------
+ /// Construct with a process.
+ // -----------------------------------------------------------------
+ SystemRuntime(lldb_private::Process *process);
+
+ //------------------------------------------------------------------
+ /// Destructor.
+ ///
+ /// The destructor is virtual since this class is designed to be
+ /// inherited by the plug-in instance.
+ //------------------------------------------------------------------
+ virtual
+ ~SystemRuntime();
+
+ //------------------------------------------------------------------
+ /// Called after attaching to a process.
+ ///
+ /// Allow the SystemRuntime plugin to execute some code after attaching
+ /// to a process.
+ //------------------------------------------------------------------
+ virtual void
+ DidAttach ();
+
+ //------------------------------------------------------------------
+ /// Called after launching a process.
+ ///
+ /// Allow the SystemRuntime plugin to execute some code after launching
+ /// a process.
+ //------------------------------------------------------------------
+ virtual void
+ DidLaunch();
+
+ //------------------------------------------------------------------
+ /// Called when modules have been loaded in the process.
+ ///
+ /// Allow the SystemRuntime plugin to enable logging features in the
+ /// system runtime libraries.
+ //------------------------------------------------------------------
+ virtual void
+ ModulesDidLoad(lldb_private::ModuleList &module_list);
+
+
+ //------------------------------------------------------------------
+ /// Return a list of thread origin extended backtraces that may
+ /// be available.
+ ///
+ /// A System Runtime may be able to provide a backtrace of when this
+ /// thread was originally created. Furthermore, it may be able to
+ /// provide that extended backtrace for different styles of creation.
+ /// On a system with both pthreads and libdispatch, aka Grand Central
+ /// Dispatch, queues, the system runtime may be able to provide the
+ /// pthread creation of the thread and it may also be able to provide
+ /// the backtrace of when this GCD queue work block was enqueued.
+ /// The caller may request these different origins by name.
+ ///
+ /// The names will be provided in the order that they are most likely
+ /// to be requested. For instance, a most natural order may be to
+ /// request the GCD libdispatch queue origin. If there is none, then
+ /// request the pthread origin.
+ ///
+ /// @return
+ /// A vector of ConstStrings with names like "pthread" or "libdispatch".
+ /// An empty vector may be returned if no thread origin extended
+ /// backtrace capabilities are available.
+ //------------------------------------------------------------------
+ virtual std::vector<ConstString>
+ GetExtendedBacktraceTypes ();
+
+ //------------------------------------------------------------------
+ /// Return a Thread which shows the origin of this thread's creation.
+ ///
+ /// This likely returns a HistoryThread which shows how thread was
+ /// originally created (e.g. "pthread" type), or how the work that
+ /// is currently executing on it was originally enqueued (e.g.
+ /// "libdispatch" type).
+ ///
+ /// There may be a chain of thread-origins; it may be informative to
+ /// the end user to query the returned ThreadSP for its origins as
+ /// well.
+ ///
+ /// @param [in] thread
+ /// The thread to examine.
+ ///
+ /// @param [in] type
+ /// The type of thread origin being requested. The types supported
+ /// are returned from SystemRuntime::GetExtendedBacktraceTypes.
+ ///
+ /// @return
+ /// A ThreadSP which will have a StackList of frames. This Thread will
+ /// not appear in the Process' list of current threads. Normal thread
+ /// operations like stepping will not be available. This is a historical
+ /// view thread and may be only useful for showing a backtrace.
+ ///
+ /// An empty ThreadSP will be returned if no thread origin is available.
+ //------------------------------------------------------------------
+ virtual lldb::ThreadSP
+ GetExtendedBacktrace (lldb::ThreadSP thread, ConstString type);
+
+protected:
+ //------------------------------------------------------------------
+ // Member variables.
+ //------------------------------------------------------------------
+ Process *m_process;
+private:
+ DISALLOW_COPY_AND_ASSIGN (SystemRuntime);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_SystemRuntime_h_
diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h
index 87fa57b3a299..1c90ea6f15eb 100644
--- a/include/lldb/Target/Target.h
+++ b/include/lldb/Target/Target.h
@@ -184,11 +184,13 @@ public:
static const uint32_t default_timeout = 500000;
EvaluateExpressionOptions() :
m_execution_policy(eExecutionPolicyOnlyWhenNeeded),
+ m_language (lldb::eLanguageTypeUnknown),
m_coerce_to_id(false),
m_unwind_on_error(true),
m_ignore_breakpoints (false),
m_keep_in_memory(false),
m_run_others(true),
+ m_debug(false),
m_use_dynamic(lldb::eNoDynamicValues),
m_timeout_usec(default_timeout)
{}
@@ -206,6 +208,19 @@ public:
return *this;
}
+ lldb::LanguageType
+ GetLanguage() const
+ {
+ return m_language;
+ }
+
+ EvaluateExpressionOptions&
+ SetLanguage(lldb::LanguageType language)
+ {
+ m_language = language;
+ return *this;
+ }
+
bool
DoesCoerceToId () const
{
@@ -297,13 +312,28 @@ public:
return *this;
}
+ bool
+ GetDebug() const
+ {
+ return m_debug;
+ }
+
+ EvaluateExpressionOptions&
+ SetDebug(bool b)
+ {
+ m_debug = b;
+ return *this;
+ }
+
private:
ExecutionPolicy m_execution_policy;
+ lldb::LanguageType m_language;
bool m_coerce_to_id;
bool m_unwind_on_error;
bool m_ignore_breakpoints;
bool m_keep_in_memory;
bool m_run_others;
+ bool m_debug;
lldb::DynamicValueType m_use_dynamic;
uint32_t m_timeout_usec;
};
@@ -503,26 +533,30 @@ public:
CreateBreakpoint (const FileSpecList *containingModules,
const FileSpec &file,
uint32_t line_no,
- LazyBool check_inlines = eLazyBoolCalculate,
- LazyBool skip_prologue = eLazyBoolCalculate,
- bool internal = false);
+ LazyBool check_inlines,
+ LazyBool skip_prologue,
+ bool internal,
+ bool request_hardware);
// Use this to create breakpoint that matches regex against the source lines in files given in source_file_list:
lldb::BreakpointSP
CreateSourceRegexBreakpoint (const FileSpecList *containingModules,
const FileSpecList *source_file_list,
RegularExpression &source_regex,
- bool internal = false);
+ bool internal,
+ bool request_hardware);
// Use this to create a breakpoint from a load address
lldb::BreakpointSP
CreateBreakpoint (lldb::addr_t load_addr,
- bool internal = false);
+ bool internal,
+ bool request_hardware);
// Use this to create Address breakpoints:
lldb::BreakpointSP
CreateBreakpoint (Address &addr,
- bool internal = false);
+ bool internal,
+ bool request_hardware);
// Use this to create a function breakpoint by regexp in containingModule/containingSourceFiles, or all modules if it is NULL
// When "skip_prologue is set to eLazyBoolCalculate, we use the current target
@@ -531,8 +565,9 @@ public:
CreateFuncRegexBreakpoint (const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
RegularExpression &func_regexp,
- LazyBool skip_prologue = eLazyBoolCalculate,
- bool internal = false);
+ LazyBool skip_prologue,
+ bool internal,
+ bool request_hardware);
// Use this to create a function breakpoint by name in containingModule, or all modules if it is NULL
// When "skip_prologue is set to eLazyBoolCalculate, we use the current target
@@ -542,11 +577,12 @@ public:
const FileSpecList *containingSourceFiles,
const char *func_name,
uint32_t func_name_type_mask,
- LazyBool skip_prologue = eLazyBoolCalculate,
- bool internal = false);
+ LazyBool skip_prologue,
+ bool internal,
+ bool request_hardware);
lldb::BreakpointSP
- CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_bp, bool throw_bp, bool internal = false);
+ CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_bp, bool throw_bp, bool internal);
// This is the same as the func_name breakpoint except that you can specify a vector of names. This is cheaper
// than a regular expression breakpoint in the case where you just want to set a breakpoint on a set of names
@@ -557,23 +593,26 @@ public:
const char *func_names[],
size_t num_names,
uint32_t func_name_type_mask,
- LazyBool skip_prologue = eLazyBoolCalculate,
- bool internal = false);
+ LazyBool skip_prologue,
+ bool internal,
+ bool request_hardware);
lldb::BreakpointSP
CreateBreakpoint (const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
const std::vector<std::string> &func_names,
uint32_t func_name_type_mask,
- LazyBool skip_prologue = eLazyBoolCalculate,
- bool internal = false);
+ LazyBool skip_prologue,
+ bool internal,
+ bool request_hardware);
// Use this to create a general breakpoint:
lldb::BreakpointSP
CreateBreakpoint (lldb::SearchFilterSP &filter_sp,
lldb::BreakpointResolverSP &resolver_sp,
- bool internal = false);
+ bool internal,
+ bool request_hardware);
// Use this to create a watchpoint:
lldb::WatchpointSP
@@ -696,11 +735,14 @@ public:
ModulesDidLoad (ModuleList &module_list);
void
- ModulesDidUnload (ModuleList &module_list);
+ ModulesDidUnload (ModuleList &module_list, bool delete_locations);
void
SymbolsDidLoad (ModuleList &module_list);
+ void
+ ClearModules();
+
//------------------------------------------------------------------
/// Gets the module for the main executable.
///
@@ -1095,21 +1137,7 @@ public:
{
return m_suppress_stop_hooks;
}
-
- bool
- SetSuppressSyntheticValue (bool suppress)
- {
- bool old_value = m_suppress_synthetic_value;
- m_suppress_synthetic_value = suppress;
- return old_value;
- }
-
- bool
- GetSuppressSyntheticValue ()
- {
- return m_suppress_synthetic_value;
- }
-
+
// StopHookSP &
// GetStopHookByIndex (size_t index);
//
diff --git a/include/lldb/Target/Thread.h b/include/lldb/Target/Thread.h
index e4e532e4b331..7dac37caa200 100644
--- a/include/lldb/Target/Thread.h
+++ b/include/lldb/Target/Thread.h
@@ -339,6 +339,12 @@ public:
return NULL;
}
+ virtual lldb::queue_id_t
+ GetQueueID ()
+ {
+ return LLDB_INVALID_QUEUE_ID;
+ }
+
virtual const char *
GetQueueName ()
{
@@ -377,7 +383,10 @@ public:
Error
ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp, bool broadcast = false);
-
+
+ Error
+ JumpToLine (const FileSpec &file, uint32_t line, bool can_leave_function, std::string *warnings = NULL);
+
virtual lldb::StackFrameSP
GetFrameWithStackID (const StackID &stack_id)
{
@@ -452,6 +461,33 @@ public:
DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx);
//------------------------------------------------------------------
+ /// Retrieves the per-thread data area.
+ /// Most OSs maintain a per-thread pointer (e.g. the FS register on
+ /// x64), which we return the value of here.
+ ///
+ /// @return
+ /// LLDB_INVALID_ADDRESS if not supported, otherwise the thread
+ /// pointer value.
+ //------------------------------------------------------------------
+ virtual lldb::addr_t
+ GetThreadPointer ();
+
+ //------------------------------------------------------------------
+ /// Retrieves the per-module TLS block for a thread.
+ ///
+ /// @param[in] module
+ /// The module to query TLS data for.
+ ///
+ /// @return
+ /// If the thread has TLS data allocated for the
+ /// module, the address of the TLS block. Otherwise
+ /// LLDB_INVALID_ADDRESS is returned.
+ //------------------------------------------------------------------
+ virtual lldb::addr_t
+ GetThreadLocalData (const lldb::ModuleSP module);
+
+
+ //------------------------------------------------------------------
// Thread Plan Providers:
// This section provides the basic thread plans that the Process control
// machinery uses to run the target. ThreadPlan.h provides more details on
diff --git a/include/lldb/Target/ThreadPlanCallFunction.h b/include/lldb/Target/ThreadPlanCallFunction.h
index d747706c6393..7b8efb60b880 100644
--- a/include/lldb/Target/ThreadPlanCallFunction.h
+++ b/include/lldb/Target/ThreadPlanCallFunction.h
@@ -136,7 +136,13 @@ public:
virtual bool
RestoreThreadState();
-
+
+ virtual void
+ ThreadDestroyed ()
+ {
+ m_takedown_done = true;
+ }
+
protected:
void ReportRegisterState (const char *message);
diff --git a/include/lldb/Target/ThreadPlanStepOverRange.h b/include/lldb/Target/ThreadPlanStepOverRange.h
index de9e66829dc7..2cb5288272ea 100644
--- a/include/lldb/Target/ThreadPlanStepOverRange.h
+++ b/include/lldb/Target/ThreadPlanStepOverRange.h
@@ -41,6 +41,8 @@ protected:
private:
+ bool IsEquivalentContext(const SymbolContext &context);
+
bool m_first_resume;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverRange);
diff --git a/include/lldb/Utility/RefCounter.h b/include/lldb/Utility/RefCounter.h
deleted file mode 100644
index 6daed5498eb8..000000000000
--- a/include/lldb/Utility/RefCounter.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//===-- RefCounter.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_RefCounter_h_
-#define liblldb_RefCounter_h_
-
-#include "lldb/lldb-public.h"
-
-namespace lldb_utility {
-
-//----------------------------------------------------------------------
-// A simple reference counter object. You need an uint32_t* to use it
-// Once that is in place, everyone who needs to ref-count, can say
-// RefCounter ref(ptr);
-// (of course, the pointer is a shared resource, and must be accessible to
-// everyone who needs it). Synchronization is handled by RefCounter itself
-// The counter is decreased each time a RefCounter to it goes out of scope
-//----------------------------------------------------------------------
-class RefCounter
-{
-public:
- typedef uint32_t value_type;
-
- RefCounter(value_type* ctr);
-
- ~RefCounter();
-
-private:
- value_type* m_counter;
- DISALLOW_COPY_AND_ASSIGN (RefCounter);
-
- template <class T>
- inline T
- increment(T* t)
- {
- return __sync_fetch_and_add(t, 1);
- }
-
- template <class T>
- inline T
- decrement(T* t)
- {
- return __sync_fetch_and_add(t, -1);
- }
-
-};
-
-} // namespace lldb_utility
-
-#endif // #ifndef liblldb_RefCounter_h_
diff --git a/include/lldb/Utility/SharingPtr.h b/include/lldb/Utility/SharingPtr.h
index 814b54b5cfe6..c451ee6e3593 100644
--- a/include/lldb/Utility/SharingPtr.h
+++ b/include/lldb/Utility/SharingPtr.h
@@ -13,6 +13,15 @@
#include <algorithm>
#include <memory>
+// Microsoft Visual C++ currently does not enable std::atomic to work
+// in CLR mode - as such we need to "hack around it" for MSVC++ builds only
+// using Windows specific instrinsics instead of the C++11 atomic support
+#ifdef _MSC_VER
+#include <intrin.h>
+#else
+#include <atomic>
+#endif
+
//#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT
#if defined (ENABLE_SP_LOGGING)
@@ -24,27 +33,17 @@ namespace lldb_private {
namespace imp {
-template <class T>
-inline T
-increment(T& t)
-{
- return __sync_add_and_fetch(&t, 1);
-}
-
-template <class T>
-inline T
-decrement(T& t)
-{
- return __sync_add_and_fetch(&t, -1);
-}
-
class shared_count
{
shared_count(const shared_count&);
shared_count& operator=(const shared_count&);
protected:
+#ifdef _MSC_VER
long shared_owners_;
+#else
+ std::atomic<long> shared_owners_;
+#endif
virtual ~shared_count();
private:
virtual void on_zero_shared() = 0;
@@ -592,14 +591,22 @@ private:
void
lldb_private::ReferenceCountedBase<T>::add_shared()
{
- imp::increment(shared_owners_);
+#ifdef _MSC_VER
+ _InterlockedIncrement(&shared_owners_);
+#else
+ ++shared_owners_;
+#endif
}
template <class T>
void
lldb_private::ReferenceCountedBase<T>::release_shared()
{
- if (imp::decrement(shared_owners_) == -1)
+#ifdef _MSC_VER
+ if (_InterlockedDecrement(&shared_owners_) == -1)
+#else
+ if (--shared_owners_ == -1)
+#endif
delete static_cast<T*>(this);
}
@@ -713,7 +720,7 @@ public:
return ptr_;
}
- operator bool() const
+ explicit operator bool() const
{
return ptr_ != 0;
}
diff --git a/include/lldb/lldb-defines.h b/include/lldb/lldb-defines.h
index 3318aa15f5ac..82307d2f5310 100644
--- a/include/lldb/lldb-defines.h
+++ b/include/lldb/lldb-defines.h
@@ -33,6 +33,7 @@
// LLDB defines
//----------------------------------------------------------------------
#define LLDB_GENERIC_ERROR UINT32_MAX
+#define LLDB_DEFAULT_SHELL "/bin/sh"
//----------------------------------------------------------------------
// Breakpoints
@@ -81,6 +82,8 @@
#define LLDB_INVALID_FRAME_ID UINT32_MAX
#define LLDB_INVALID_SIGNAL_NUMBER INT32_MAX
#define LLDB_INVALID_OFFSET UINT64_MAX // Must match max of lldb::offset_t
+#define LLDB_INVALID_LINE_NUMBER UINT32_MAX
+#define LLDB_INVALID_QUEUE_ID 0
//----------------------------------------------------------------------
/// CPU Type defintions
@@ -109,6 +112,15 @@
#define LLDB_OPT_SET_10 (1U << 9)
#define LLDB_OPT_SET_FROM_TO(A, B) (((1U << (B)) - 1) ^ (((1U << (A))-1) >> 1))
+#ifdef _WIN32
+#define MAX_PATH 260
+#endif
+
+#ifdef _MSC_VER
+// ignore GCC function attributes
+#define __attribute__(X)
+#endif
+
#if defined(__cplusplus)
//----------------------------------------------------------------------
diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h
index 6ec5ed6a35e2..ae8c92be900b 100644
--- a/include/lldb/lldb-enumerations.h
+++ b/include/lldb/lldb-enumerations.h
@@ -380,6 +380,7 @@ namespace lldb {
eArgTypeClassName,
eArgTypeCommandName,
eArgTypeCount,
+ eArgTypeDescriptionVerbosity,
eArgTypeDirectoryName,
eArgTypeDisassemblyFlavor,
eArgTypeEndAddress,
@@ -406,6 +407,9 @@ namespace lldb {
eArgTypeOffset,
eArgTypeOldPathPrefix,
eArgTypeOneLiner,
+ eArgTypePath,
+ eArgTypePermissionsNumber,
+ eArgTypePermissionsString,
eArgTypePid,
eArgTypePlugin,
eArgTypeProcessName,
@@ -480,7 +484,8 @@ namespace lldb {
eSymbolTypeUndefined,
eSymbolTypeObjCClass,
eSymbolTypeObjCMetaClass,
- eSymbolTypeObjCIVar
+ eSymbolTypeObjCIVar,
+ eSymbolTypeReExported
} SymbolType;
typedef enum SectionType
diff --git a/include/lldb/lldb-forward.h b/include/lldb/lldb-forward.h
index 84af8b646901..cd8a5c2e8130 100644
--- a/include/lldb/lldb-forward.h
+++ b/include/lldb/lldb-forward.h
@@ -79,6 +79,7 @@ class DataExtractor;
class Debugger;
class Declaration;
class Disassembler;
+struct DumpValueObjectOptions;
class DynamicLibrary;
class DynamicLoader;
class EmulateInstruction;
@@ -90,6 +91,7 @@ class ExecutionContext;
class ExecutionContextRef;
class ExecutionContextRefLocker;
class ExecutionContextScope;
+class File;
class FileSpec;
class FileSpecList;
class Flags;
@@ -104,6 +106,7 @@ class Instruction;
class InstructionList;
class IRExecutionUnit;
class LanguageRuntime;
+class SystemRuntime;
class LineTable;
class Listener;
class Log;
@@ -119,6 +122,7 @@ struct NameSearchContext;
class ObjCLanguageRuntime;
class ObjectContainer;
class OptionGroup;
+class OptionGroupOptions;
class OptionGroupPlatform;
class ObjectFile;
class OperatingSystem;
@@ -224,13 +228,14 @@ class ThreadPlanTracer;
class ThreadSpec;
class TimeValue;
class Type;
+class TypeAndOrName;
class TypeCategoryMap;
class TypeImpl;
-class TypeAndOrName;
class TypeList;
class TypeListImpl;
class TypeMemberImpl;
class TypeNameSpecifierImpl;
+class TypePair;
class UUID;
class Unwind;
class UnwindAssembly;
@@ -246,6 +251,7 @@ class ValueObjectConstResult;
class ValueObjectConstResultChild;
class ValueObjectConstResultImpl;
class ValueObjectList;
+class ValueObjectPrinter;
class Variable;
class VariableList;
class Watchpoint;
@@ -285,12 +291,14 @@ namespace lldb {
typedef std::shared_ptr<lldb_private::DynamicLoader> DynamicLoaderSP;
typedef std::shared_ptr<lldb_private::Event> EventSP;
typedef std::shared_ptr<lldb_private::ExecutionContextRef> ExecutionContextRefSP;
+ typedef std::shared_ptr<lldb_private::File> FileSP;
typedef std::shared_ptr<lldb_private::Function> FunctionSP;
typedef std::shared_ptr<lldb_private::FuncUnwinders> FuncUnwindersSP;
typedef std::shared_ptr<lldb_private::InlineFunctionInfo> InlineFunctionInfoSP;
typedef std::shared_ptr<lldb_private::InputReader> InputReaderSP;
typedef std::shared_ptr<lldb_private::Instruction> InstructionSP;
typedef std::shared_ptr<lldb_private::LanguageRuntime> LanguageRuntimeSP;
+ typedef std::shared_ptr<lldb_private::SystemRuntime> SystemRuntimeSP;
typedef std::shared_ptr<lldb_private::LineTable> LineTableSP;
typedef std::shared_ptr<lldb_private::Listener> ListenerSP;
typedef std::shared_ptr<lldb_private::LogChannel> LogChannelSP;
diff --git a/include/lldb/lldb-private-enumerations.h b/include/lldb/lldb-private-enumerations.h
index 60c90907145f..e523b912eac6 100644
--- a/include/lldb/lldb-private-enumerations.h
+++ b/include/lldb/lldb-private-enumerations.h
@@ -51,6 +51,7 @@ typedef enum ArchitectureType
eArchTypeInvalid,
eArchTypeMachO,
eArchTypeELF,
+ eArchTypeCOFF,
kNumArchTypes
} ArchitectureType;
@@ -191,7 +192,9 @@ typedef enum FormatCategoryItem
eFormatCategoryItemFilter = 0x0004,
eFormatCategoryItemRegexFilter = 0x0008,
eFormatCategoryItemSynth = 0x0010,
- eFormatCategoryItemRegexSynth = 0x0020
+ eFormatCategoryItemRegexSynth = 0x0020,
+ eFormatCategoryItemValue = 0x0040,
+ eFormatCategoryItemRegexValue = 0x0080
} FormatCategoryItem;
//------------------------------------------------------------------
@@ -228,6 +231,14 @@ typedef enum ScriptedCommandSynchronicity
eScriptedCommandSynchronicityCurrentValue // use whatever the current synchronicity is
} ScriptedCommandSynchronicity;
+//----------------------------------------------------------------------
+// Verbosity mode of "po" output
+//----------------------------------------------------------------------
+typedef enum LanguageRuntimeDescriptionDisplayVerbosity
+{
+ eLanguageRuntimeDescriptionDisplayVerbosityCompact, // only print the description string, if any
+ eLanguageRuntimeDescriptionDisplayVerbosityFull, // print the full-blown output
+} LanguageRuntimeDescriptionDisplayVerbosity;
//----------------------------------------------------------------------
// Loading modules from memory
diff --git a/include/lldb/lldb-private-interfaces.h b/include/lldb/lldb-private-interfaces.h
index 949cafed98b3..5a2da8989f35 100644
--- a/include/lldb/lldb-private-interfaces.h
+++ b/include/lldb/lldb-private-interfaces.h
@@ -27,6 +27,7 @@ namespace lldb_private
typedef EmulateInstruction * (*EmulateInstructionCreateInstance) (const ArchSpec &arch, InstructionType inst_type);
typedef OperatingSystem* (*OperatingSystemCreateInstance) (Process *process, bool force);
typedef LanguageRuntime *(*LanguageRuntimeCreateInstance) (Process *process, lldb::LanguageType language);
+ typedef SystemRuntime *(*SystemRuntimeCreateInstance) (Process *process);
typedef Platform* (*PlatformCreateInstance) (bool force, const ArchSpec *arch);
typedef lldb::ProcessSP (*ProcessCreateInstance) (Target &target, Listener &listener, const FileSpec *crash_file_path);
typedef SymbolFile* (*SymbolFileCreateInstance) (ObjectFile* obj_file);
diff --git a/include/lldb/lldb-private-log.h b/include/lldb/lldb-private-log.h
index 31a1c23c5e67..48cce69d36cc 100644
--- a/include/lldb/lldb-private-log.h
+++ b/include/lldb/lldb-private-log.h
@@ -44,6 +44,7 @@
#define LIBLLDB_LOG_TARGET (1u << 22)
#define LIBLLDB_LOG_MMAP (1u << 23)
#define LIBLLDB_LOG_OS (1u << 24)
+#define LIBLLDB_LOG_PLATFORM (1u << 25)
#define LIBLLDB_LOG_ALL (UINT32_MAX)
#define LIBLLDB_LOG_DEFAULT (LIBLLDB_LOG_PROCESS |\
LIBLLDB_LOG_THREAD |\
diff --git a/include/lldb/lldb-private.h b/include/lldb/lldb-private.h
index 90590601d945..05b2c4fd6381 100644
--- a/include/lldb/lldb-private.h
+++ b/include/lldb/lldb-private.h
@@ -12,6 +12,10 @@
#if defined(__cplusplus)
+#ifdef _WIN32
+#include "lldb/Host/windows/win32.h"
+#endif
+
#include "lldb/lldb-public.h"
#include "lldb/lldb-private-enumerations.h"
#include "lldb/lldb-private-interfaces.h"
diff --git a/include/lldb/lldb-types.h b/include/lldb/lldb-types.h
index 2693c0c822bb..5851b5d3f923 100644
--- a/include/lldb/lldb-types.h
+++ b/include/lldb/lldb-types.h
@@ -14,11 +14,8 @@
#include "lldb/lldb-forward.h"
#include <assert.h>
-#include <pthread.h>
#include <signal.h>
#include <stdint.h>
-#include <stdbool.h>
-#include <unistd.h>
//----------------------------------------------------------------------
// All host systems must define:
@@ -38,13 +35,42 @@
// things should be defined. Currently MacOSX is being assumed by default
// since that is what lldb was first developed for.
+#ifndef _MSC_VER
+#include <stdbool.h>
+#include <unistd.h>
+#endif
+
+#ifdef _WIN32
+
+#include <process.h>
+
+namespace lldb
+{
+ typedef void* mutex_t;
+ typedef void* condition_t;
+ typedef void* rwlock_t;
+ typedef uintptr_t thread_t; // Host thread type
+ typedef uint32_t thread_key_t;
+ typedef void * thread_arg_t; // Host thread argument type
+ typedef unsigned thread_result_t; // Host thread result type
+ typedef thread_result_t (*thread_func_t)(void *); // Host thread function type
+ typedef void (*LogOutputCallback) (const char *, void *baton);
+ typedef bool (*CommandOverrideCallback)(void *baton, const char **argv);
+}
+
+#else
+
+#include <pthread.h>
+
namespace lldb {
//----------------------------------------------------------------------
// MacOSX Types
//----------------------------------------------------------------------
typedef ::pthread_mutex_t mutex_t;
typedef pthread_cond_t condition_t;
+ typedef pthread_rwlock_t rwlock_t;
typedef pthread_t thread_t; // Host thread type
+ typedef pthread_key_t thread_key_t;
typedef void * thread_arg_t; // Host thread argument type
typedef void * thread_result_t; // Host thread result type
typedef void * (*thread_func_t)(void *); // Host thread function type
@@ -52,19 +78,11 @@ namespace lldb {
typedef bool (*CommandOverrideCallback)(void *baton, const char **argv);
} // namespace lldb
-#if defined(__MINGW32__)
-
-const lldb::thread_t lldb_invalid_host_thread_const = { NULL, 0 } ;
-#define LLDB_INVALID_HOST_THREAD (lldb_invalid_host_thread_const)
-#define IS_VALID_LLDB_HOST_THREAD(t) (!(NULL == (t).p && 0 == (t).x))
-
-#else
+#endif
#define LLDB_INVALID_HOST_THREAD ((lldb::thread_t)NULL)
#define IS_VALID_LLDB_HOST_THREAD(t) ((t) != LLDB_INVALID_HOST_THREAD)
-#endif
-
#define LLDB_INVALID_HOST_TIME { 0, 0 }
namespace lldb
@@ -77,6 +95,7 @@ namespace lldb
typedef int32_t break_id_t;
typedef int32_t watch_id_t;
typedef void * clang_type_t;
+ typedef uint64_t queue_id_t;
}
diff --git a/include/lldb/lldb-versioning.h b/include/lldb/lldb-versioning.h
index 8ccc67d8e9c0..d0498a569f58 100644
--- a/include/lldb/lldb-versioning.h
+++ b/include/lldb/lldb-versioning.h
@@ -1604,4 +1604,4 @@
#define LLDB_API_DEPRECATED_IN_DOT_99
#endif // defined(LLDB_CHECK_API_VERSIONING) && defined(LLDB_API_MAJOR_VERSION_WANTED) && defined(LLDB_API_MINOR_VERSION_WANTED) && defined (LLDB_API_MAJOR_VERSION)
-#endif // LLDB_lldb_versioning_h_ \ No newline at end of file
+#endif // LLDB_lldb_versioning_h_
diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp
index 0c839004601c..ac77e2e41126 100644
--- a/source/API/SBCommandInterpreter.cpp
+++ b/source/API/SBCommandInterpreter.cpp
@@ -384,15 +384,103 @@ SBCommandInterpreter::SetCommandOverrideCallback (const char *command_name,
extern "C" void
init_lldb(void);
-#else
+// these are the Pythonic implementations of the required callbacks
+// these are scripting-language specific, which is why they belong here
+// we still need to use function pointers to them instead of relying
+// on linkage-time resolution because the SWIG stuff and this file
+// get built at different times
+extern "C" bool
+LLDBSwigPythonBreakpointCallbackFunction (const char *python_function_name,
+ const char *session_dictionary_name,
+ const lldb::StackFrameSP& sb_frame,
+ const lldb::BreakpointLocationSP& sb_bp_loc);
+
+extern "C" bool
+LLDBSwigPythonWatchpointCallbackFunction (const char *python_function_name,
+ const char *session_dictionary_name,
+ const lldb::StackFrameSP& sb_frame,
+ const lldb::WatchpointSP& sb_wp);
+
+extern "C" bool
+LLDBSwigPythonCallTypeScript (const char *python_function_name,
+ void *session_dictionary,
+ const lldb::ValueObjectSP& valobj_sp,
+ void** pyfunct_wrapper,
+ std::string& retval);
+
+extern "C" void*
+LLDBSwigPythonCreateSyntheticProvider (const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ValueObjectSP& valobj_sp);
+
+
+extern "C" uint32_t
+LLDBSwigPython_CalculateNumChildren (void *implementor);
+
+extern "C" void *
+LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx);
+
+extern "C" int
+LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name);
+
+extern "C" void *
+LLDBSWIGPython_CastPyObjectToSBValue (void* data);
+
+extern lldb::ValueObjectSP
+LLDBSWIGPython_GetValueObjectSPFromSBValue (void* data);
+
+extern "C" bool
+LLDBSwigPython_UpdateSynthProviderInstance (void* implementor);
+
+extern "C" bool
+LLDBSwigPython_MightHaveChildrenSynthProviderInstance (void* implementor);
+
+extern "C" bool
+LLDBSwigPythonCallCommand (const char *python_function_name,
+ const char *session_dictionary_name,
+ lldb::DebuggerSP& debugger,
+ const char* args,
+ lldb_private::CommandReturnObject &cmd_retobj);
+
+extern "C" bool
+LLDBSwigPythonCallModuleInit (const char *python_module_name,
+ const char *session_dictionary_name,
+ lldb::DebuggerSP& debugger);
+
+extern "C" void*
+LLDBSWIGPythonCreateOSPlugin (const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ProcessSP& process_sp);
+
+extern "C" bool
+LLDBSWIGPythonRunScriptKeywordProcess (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::ProcessSP& process,
+ std::string& output);
+
+extern "C" bool
+LLDBSWIGPythonRunScriptKeywordThread (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::ThreadSP& thread,
+ std::string& output);
+
+extern "C" bool
+LLDBSWIGPythonRunScriptKeywordTarget (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::TargetSP& target,
+ std::string& output);
+
+extern "C" bool
+LLDBSWIGPythonRunScriptKeywordFrame (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::StackFrameSP& frame,
+ std::string& output);
+
+extern "C" void*
+LLDBSWIGPython_GetDynamicSetting (void* module,
+ const char* setting,
+ const lldb::TargetSP& target_sp);
-extern "C" void init_lldb(void);
-
-// Usually defined in the SWIG source file, but we have sripting disabled
-extern "C" void
-init_lldb(void)
-{
-}
#endif
@@ -404,7 +492,26 @@ SBCommandInterpreter::InitializeSWIG ()
{
g_initialized = true;
#ifndef LLDB_DISABLE_PYTHON
- ScriptInterpreter::InitializeInterpreter (init_lldb);
+ ScriptInterpreter::InitializeInterpreter (init_lldb,
+ LLDBSwigPythonBreakpointCallbackFunction,
+ LLDBSwigPythonWatchpointCallbackFunction,
+ LLDBSwigPythonCallTypeScript,
+ LLDBSwigPythonCreateSyntheticProvider,
+ LLDBSwigPython_CalculateNumChildren,
+ LLDBSwigPython_GetChildAtIndex,
+ LLDBSwigPython_GetIndexOfChildWithName,
+ LLDBSWIGPython_CastPyObjectToSBValue,
+ LLDBSWIGPython_GetValueObjectSPFromSBValue,
+ LLDBSwigPython_UpdateSynthProviderInstance,
+ LLDBSwigPython_MightHaveChildrenSynthProviderInstance,
+ LLDBSwigPythonCallCommand,
+ LLDBSwigPythonCallModuleInit,
+ LLDBSWIGPythonCreateOSPlugin,
+ LLDBSWIGPythonRunScriptKeywordProcess,
+ LLDBSWIGPythonRunScriptKeywordThread,
+ LLDBSWIGPythonRunScriptKeywordTarget,
+ LLDBSWIGPythonRunScriptKeywordFrame,
+ LLDBSWIGPython_GetDynamicSetting);
#endif
}
}
diff --git a/source/API/SBData.cpp b/source/API/SBData.cpp
index 5b2f075158b8..06dcfc12af41 100644
--- a/source/API/SBData.cpp
+++ b/source/API/SBData.cpp
@@ -122,7 +122,7 @@ SBData::GetByteSize ()
value = m_opaque_sp->GetByteSize();
if (log)
log->Printf ("SBData::GetByteSize () => "
- "(%lu)", value);
+ "(%zu)", value);
return value;
}
@@ -479,7 +479,7 @@ SBData::ReadRawData (lldb::SBError& error,
error.SetErrorString("unable to read data");
}
if (log)
- log->Printf ("SBData::ReadRawData (error=%p,offset=%" PRIu64 ",buf=%p,size=%lu) => "
+ log->Printf ("SBData::ReadRawData (error=%p,offset=%" PRIu64 ",buf=%p,size=%zu) => "
"(%p)", error.get(), offset, buf, size, ok);
return ok ? size : 0;
}
@@ -497,7 +497,7 @@ SBData::SetData (lldb::SBError& error,
else
m_opaque_sp->SetData(buf, size, endian);
if (log)
- log->Printf ("SBData::SetData (error=%p,buf=%p,size=%lu,endian=%d,addr_size=%c) => "
+ 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());
}
@@ -647,7 +647,7 @@ SBData::SetDataFromUInt64Array (uint64_t* array, size_t array_len)
if (!array || array_len == 0)
{
if (log)
- log->Printf ("SBData::SetDataFromUInt64Array (array=%p, array_len = %lu) => "
+ log->Printf ("SBData::SetDataFromUInt64Array (array=%p, array_len = %zu) => "
"false", array, array_len);
return false;
}
@@ -662,7 +662,7 @@ SBData::SetDataFromUInt64Array (uint64_t* array, size_t array_len)
m_opaque_sp->SetData(buffer_sp);
if (log)
- log->Printf ("SBData::SetDataFromUInt64Array (array=%p, array_len = %lu) => "
+ log->Printf ("SBData::SetDataFromUInt64Array (array=%p, array_len = %zu) => "
"true", array, array_len);
return true;
@@ -676,7 +676,7 @@ SBData::SetDataFromUInt32Array (uint32_t* array, size_t array_len)
if (!array || array_len == 0)
{
if (log)
- log->Printf ("SBData::SetDataFromUInt32Array (array=%p, array_len = %lu) => "
+ log->Printf ("SBData::SetDataFromUInt32Array (array=%p, array_len = %zu) => "
"false", array, array_len);
return false;
}
@@ -691,7 +691,7 @@ SBData::SetDataFromUInt32Array (uint32_t* array, size_t array_len)
m_opaque_sp->SetData(buffer_sp);
if (log)
- log->Printf ("SBData::SetDataFromUInt32Array (array=%p, array_len = %lu) => "
+ log->Printf ("SBData::SetDataFromUInt32Array (array=%p, array_len = %zu) => "
"true", array, array_len);
return true;
@@ -705,7 +705,7 @@ SBData::SetDataFromSInt64Array (int64_t* array, size_t array_len)
if (!array || array_len == 0)
{
if (log)
- log->Printf ("SBData::SetDataFromSInt64Array (array=%p, array_len = %lu) => "
+ log->Printf ("SBData::SetDataFromSInt64Array (array=%p, array_len = %zu) => "
"false", array, array_len);
return false;
}
@@ -720,7 +720,7 @@ SBData::SetDataFromSInt64Array (int64_t* array, size_t array_len)
m_opaque_sp->SetData(buffer_sp);
if (log)
- log->Printf ("SBData::SetDataFromSInt64Array (array=%p, array_len = %lu) => "
+ log->Printf ("SBData::SetDataFromSInt64Array (array=%p, array_len = %zu) => "
"true", array, array_len);
return true;
@@ -734,7 +734,7 @@ SBData::SetDataFromSInt32Array (int32_t* array, size_t array_len)
if (!array || array_len == 0)
{
if (log)
- log->Printf ("SBData::SetDataFromSInt32Array (array=%p, array_len = %lu) => "
+ log->Printf ("SBData::SetDataFromSInt32Array (array=%p, array_len = %zu) => "
"false", array, array_len);
return false;
}
@@ -749,7 +749,7 @@ SBData::SetDataFromSInt32Array (int32_t* array, size_t array_len)
m_opaque_sp->SetData(buffer_sp);
if (log)
- log->Printf ("SBData::SetDataFromSInt32Array (array=%p, array_len = %lu) => "
+ log->Printf ("SBData::SetDataFromSInt32Array (array=%p, array_len = %zu) => "
"true", array, array_len);
return true;
@@ -763,7 +763,7 @@ SBData::SetDataFromDoubleArray (double* array, size_t array_len)
if (!array || array_len == 0)
{
if (log)
- log->Printf ("SBData::SetDataFromDoubleArray (array=%p, array_len = %lu) => "
+ log->Printf ("SBData::SetDataFromDoubleArray (array=%p, array_len = %zu) => "
"false", array, array_len);
return false;
}
@@ -778,7 +778,7 @@ SBData::SetDataFromDoubleArray (double* array, size_t array_len)
m_opaque_sp->SetData(buffer_sp);
if (log)
- log->Printf ("SBData::SetDataFromDoubleArray (array=%p, array_len = %lu) => "
+ log->Printf ("SBData::SetDataFromDoubleArray (array=%p, array_len = %zu) => "
"true", array, array_len);
return true;
diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp
index f5e71d5f1a07..88c991b72054 100644
--- a/source/API/SBDebugger.cpp
+++ b/source/API/SBDebugger.cpp
@@ -480,7 +480,7 @@ SBDebugger::GetScriptingLanguage (const char *script_language_name)
const char *
SBDebugger::GetVersionString ()
{
- return GetVersion();
+ return lldb_private::GetVersion();
}
const char *
@@ -711,7 +711,7 @@ SBDebugger::GetIndexOfTarget (lldb::SBTarget target)
}
SBTarget
-SBDebugger::FindTargetWithProcessID (pid_t pid)
+SBDebugger::FindTargetWithProcessID (lldb::pid_t pid)
{
SBTarget sb_target;
if (m_opaque_sp)
diff --git a/source/API/SBFileSpec.cpp b/source/API/SBFileSpec.cpp
index 4413689501a8..fc207d071dbc 100644
--- a/source/API/SBFileSpec.cpp
+++ b/source/API/SBFileSpec.cpp
@@ -61,7 +61,7 @@ SBFileSpec::operator = (const SBFileSpec &rhs)
bool
SBFileSpec::IsValid() const
{
- return *m_opaque_ap;
+ return m_opaque_ap->operator bool();
}
bool
diff --git a/source/API/SBFunction.cpp b/source/API/SBFunction.cpp
index 914d2d77f3ec..bb7ea2e9f202 100644
--- a/source/API/SBFunction.cpp
+++ b/source/API/SBFunction.cpp
@@ -143,11 +143,13 @@ SBFunction::GetInstructions (SBTarget target, const char *flavor)
ModuleSP module_sp (m_opaque_ptr->GetAddressRange().GetBaseAddress().GetModule());
if (module_sp)
{
+ const bool prefer_file_cache = false;
sb_instructions.SetDisassembler (Disassembler::DisassembleRange (module_sp->GetArchitecture(),
NULL,
flavor,
exe_ctx,
- m_opaque_ptr->GetAddressRange()));
+ m_opaque_ptr->GetAddressRange(),
+ prefer_file_cache));
}
}
return sb_instructions;
diff --git a/source/API/SBHostOS.cpp b/source/API/SBHostOS.cpp
index a8f7db90a150..166403103ad5 100644
--- a/source/API/SBHostOS.cpp
+++ b/source/API/SBHostOS.cpp
@@ -42,7 +42,7 @@ lldb::thread_t
SBHostOS::ThreadCreate
(
const char *name,
- void *(*thread_function)(void *),
+ thread_func_t thread_function,
void *thread_arg,
SBError *error_ptr
)
@@ -77,7 +77,7 @@ SBHostOS::ThreadDetach (lldb::thread_t thread, SBError *error_ptr)
}
bool
-SBHostOS::ThreadJoin (lldb::thread_t thread, void **result, SBError *error_ptr)
+SBHostOS::ThreadJoin (lldb::thread_t thread, thread_result_t *result, SBError *error_ptr)
{
return Host::ThreadJoin (thread, result, error_ptr ? error_ptr->get() : NULL);
}
diff --git a/source/API/SBModuleSpec.cpp b/source/API/SBModuleSpec.cpp
index 654a8ca6ec86..17c83abb4f24 100644
--- a/source/API/SBModuleSpec.cpp
+++ b/source/API/SBModuleSpec.cpp
@@ -44,7 +44,7 @@ SBModuleSpec::~SBModuleSpec ()
bool
SBModuleSpec::IsValid () const
{
- return *m_opaque_ap;
+ return m_opaque_ap->operator bool();
}
void
diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp
index 259eb5e97034..d690da7eed87 100644
--- a/source/API/SBProcess.cpp
+++ b/source/API/SBProcess.cpp
@@ -11,6 +11,9 @@
#include "lldb/API/SBProcess.h"
+// C Includes
+#include <inttypes.h>
+
#include "lldb/lldb-defines.h"
#include "lldb/lldb-types.h"
@@ -23,6 +26,7 @@
#include "lldb/Core/StreamFile.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -334,7 +338,7 @@ SBProcess::PutSTDIN (const char *src, size_t src_len)
}
if (log)
- log->Printf ("SBProcess(%p)::PutSTDIN (src=\"%s\", src_len=%d) => %lu",
+ log->Printf ("SBProcess(%p)::PutSTDIN (src=\"%s\", src_len=%d) => %zu",
process_sp.get(),
src,
(uint32_t) src_len,
@@ -1254,3 +1258,37 @@ SBProcess::UnloadImage (uint32_t image_token)
sb_error.SetErrorString("invalid process");
return sb_error;
}
+
+uint32_t
+SBProcess::GetNumExtendedBacktraceTypes ()
+{
+ ProcessSP process_sp(GetSP());
+ if (process_sp && process_sp->GetSystemRuntime())
+ {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime();
+ return runtime->GetExtendedBacktraceTypes().size();
+ }
+ return 0;
+}
+
+const char *
+SBProcess::GetExtendedBacktraceTypeAtIndex (uint32_t idx)
+{
+ ProcessSP process_sp(GetSP());
+ if (process_sp && process_sp->GetSystemRuntime())
+ {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime();
+ std::vector<ConstString> names = runtime->GetExtendedBacktraceTypes();
+ if (idx < names.size())
+ {
+ return names[idx].AsCString();
+ }
+ else
+ {
+ 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());
+ }
+ }
+ return NULL;
+}
diff --git a/source/API/SBSymbol.cpp b/source/API/SBSymbol.cpp
index dd057e81a559..ef3d0764c963 100644
--- a/source/API/SBSymbol.cpp
+++ b/source/API/SBSymbol.cpp
@@ -139,11 +139,13 @@ SBSymbol::GetInstructions (SBTarget target, const char *flavor_string)
if (module_sp)
{
AddressRange symbol_range (m_opaque_ptr->GetAddress(), m_opaque_ptr->GetByteSize());
+ const bool prefer_file_cache = false;
sb_instructions.SetDisassembler (Disassembler::DisassembleRange (module_sp->GetArchitecture (),
NULL,
flavor_string,
exe_ctx,
- symbol_range));
+ symbol_range,
+ prefer_file_cache));
}
}
}
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index f37c8f8a614b..cff6e4e2de36 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -41,6 +41,7 @@
#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/STLUtils.h"
+#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Host/FileSpec.h"
@@ -1260,7 +1261,8 @@ SBTarget::ResolveLoadAddress (lldb::addr_t vm_addr)
}
SBSymbolContext
-SBTarget::ResolveSymbolContextForAddress (const SBAddress& addr, uint32_t resolve_scope)
+SBTarget::ResolveSymbolContextForAddress (const SBAddress& addr,
+ uint32_t resolve_scope)
{
SBSymbolContext sc;
if (addr.IsValid())
@@ -1274,13 +1276,15 @@ SBTarget::ResolveSymbolContextForAddress (const SBAddress& addr, uint32_t resolv
SBBreakpoint
-SBTarget::BreakpointCreateByLocation (const char *file, uint32_t line)
+SBTarget::BreakpointCreateByLocation (const char *file,
+ uint32_t line)
{
return SBBreakpoint(BreakpointCreateByLocation (SBFileSpec (file, false), line));
}
SBBreakpoint
-SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, uint32_t line)
+SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec,
+ uint32_t line)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -1293,7 +1297,8 @@ SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, uint32_t l
const LazyBool check_inlines = eLazyBoolCalculate;
const LazyBool skip_prologue = eLazyBoolCalculate;
const bool internal = false;
- *sb_bp = target_sp->CreateBreakpoint (NULL, *sb_file_spec, line, check_inlines, skip_prologue, internal);
+ const bool hardware = false;
+ *sb_bp = target_sp->CreateBreakpoint (NULL, *sb_file_spec, line, check_inlines, skip_prologue, internal, hardware);
}
if (log)
@@ -1314,7 +1319,8 @@ SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, uint32_t l
}
SBBreakpoint
-SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_name)
+SBTarget::BreakpointCreateByName (const char *symbol_name,
+ const char *module_name)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -1325,16 +1331,17 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_na
Mutex::Locker api_locker (target_sp->GetAPIMutex());
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->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal);
+ *sb_bp = target_sp->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal, hardware);
}
else
{
- *sb_bp = target_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal);
+ *sb_bp = target_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal, hardware);
}
}
@@ -1349,8 +1356,8 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_na
lldb::SBBreakpoint
SBTarget::BreakpointCreateByName (const char *symbol_name,
- const SBFileSpecList &module_list,
- const SBFileSpecList &comp_unit_list)
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &comp_unit_list)
{
uint32_t name_type_mask = eFunctionNameTypeAuto;
return BreakpointCreateByName (symbol_name, name_type_mask, module_list, comp_unit_list);
@@ -1358,9 +1365,9 @@ SBTarget::BreakpointCreateByName (const char *symbol_name,
lldb::SBBreakpoint
SBTarget::BreakpointCreateByName (const char *symbol_name,
- uint32_t name_type_mask,
- const SBFileSpecList &module_list,
- const SBFileSpecList &comp_unit_list)
+ uint32_t name_type_mask,
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &comp_unit_list)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -1369,14 +1376,16 @@ SBTarget::BreakpointCreateByName (const char *symbol_name,
if (target_sp && symbol_name && symbol_name[0])
{
const bool internal = false;
+ const bool hardware = false;
const LazyBool skip_prologue = eLazyBoolCalculate;
Mutex::Locker api_locker (target_sp->GetAPIMutex());
*sb_bp = target_sp->CreateBreakpoint (module_list.get(),
- comp_unit_list.get(),
- symbol_name,
- name_type_mask,
- skip_prologue,
- internal);
+ comp_unit_list.get(),
+ symbol_name,
+ name_type_mask,
+ skip_prologue,
+ internal,
+ hardware);
}
if (log)
@@ -1403,6 +1412,7 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[],
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
const bool internal = false;
+ const bool hardware = false;
const LazyBool skip_prologue = eLazyBoolCalculate;
*sb_bp = target_sp->CreateBreakpoint (module_list.get(),
comp_unit_list.get(),
@@ -1410,7 +1420,8 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[],
num_names,
name_type_mask,
skip_prologue,
- internal);
+ internal,
+ hardware);
}
if (log)
@@ -1436,7 +1447,8 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[],
}
SBBreakpoint
-SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name)
+SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
+ const char *module_name)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -1447,6 +1459,7 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *mo
Mutex::Locker api_locker (target_sp->GetAPIMutex());
RegularExpression regexp(symbol_name_regex);
const bool internal = false;
+ const bool hardware = false;
const LazyBool skip_prologue = eLazyBoolCalculate;
if (module_name && module_name[0])
@@ -1454,11 +1467,11 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *mo
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);
+ *sb_bp = target_sp->CreateFuncRegexBreakpoint (&module_spec_list, NULL, regexp, skip_prologue, internal, hardware);
}
else
{
- *sb_bp = target_sp->CreateFuncRegexBreakpoint (NULL, NULL, regexp, skip_prologue, internal);
+ *sb_bp = target_sp->CreateFuncRegexBreakpoint (NULL, NULL, regexp, skip_prologue, internal, hardware);
}
}
@@ -1473,8 +1486,8 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *mo
lldb::SBBreakpoint
SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
- const SBFileSpecList &module_list,
- const SBFileSpecList &comp_unit_list)
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &comp_unit_list)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -1485,9 +1498,10 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
Mutex::Locker api_locker (target_sp->GetAPIMutex());
RegularExpression regexp(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);
+ *sb_bp = target_sp->CreateFuncRegexBreakpoint (module_list.get(), comp_unit_list.get(), regexp, skip_prologue, internal, hardware);
}
if (log)
@@ -1509,7 +1523,8 @@ SBTarget::BreakpointCreateByAddress (addr_t address)
if (target_sp)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
- *sb_bp = target_sp->CreateBreakpoint (address, false);
+ const bool hardware = false;
+ *sb_bp = target_sp->CreateBreakpoint (address, false, hardware);
}
if (log)
@@ -1521,7 +1536,9 @@ SBTarget::BreakpointCreateByAddress (addr_t address)
}
lldb::SBBreakpoint
-SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::SBFileSpec &source_file, const char *module_name)
+SBTarget::BreakpointCreateBySourceRegex (const char *source_regex,
+ const lldb::SBFileSpec &source_file,
+ const char *module_name)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -1532,6 +1549,7 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::S
Mutex::Locker api_locker (target_sp->GetAPIMutex());
RegularExpression regexp(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])
@@ -1539,11 +1557,11 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::S
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);
+ *sb_bp = target_sp->CreateSourceRegexBreakpoint (&module_spec_list, &source_file_spec_list, regexp, false, hardware);
}
else
{
- *sb_bp = target_sp->CreateSourceRegexBreakpoint (NULL, &source_file_spec_list, regexp, false);
+ *sb_bp = target_sp->CreateSourceRegexBreakpoint (NULL, &source_file_spec_list, regexp, false, hardware);
}
}
@@ -1560,8 +1578,8 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::S
lldb::SBBreakpoint
SBTarget::BreakpointCreateBySourceRegex (const char *source_regex,
- const SBFileSpecList &module_list,
- const lldb::SBFileSpecList &source_file_list)
+ const SBFileSpecList &module_list,
+ const lldb::SBFileSpecList &source_file_list)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -1570,8 +1588,9 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex,
if (target_sp && source_regex && source_regex[0])
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
+ const bool hardware = false;
RegularExpression regexp(source_regex);
- *sb_bp = target_sp->CreateSourceRegexBreakpoint (module_list.get(), source_file_list.get(), regexp, false);
+ *sb_bp = target_sp->CreateSourceRegexBreakpoint (module_list.get(), source_file_list.get(), regexp, false, hardware);
}
if (log)
@@ -1585,8 +1604,8 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex,
lldb::SBBreakpoint
SBTarget::BreakpointCreateForException (lldb::LanguageType language,
- bool catch_bp,
- bool throw_bp)
+ bool catch_bp,
+ bool throw_bp)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -1595,7 +1614,8 @@ SBTarget::BreakpointCreateForException (lldb::LanguageType language,
if (target_sp)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
- *sb_bp = target_sp->CreateExceptionBreakpoint (language, catch_bp, throw_bp);
+ const bool hardware = false;
+ *sb_bp = target_sp->CreateExceptionBreakpoint (language, catch_bp, throw_bp, hardware);
}
if (log)
@@ -1862,6 +1882,50 @@ SBTarget::DisableAllWatchpoints ()
return false;
}
+SBValue
+SBTarget::CreateValueFromAddress (const char *name, SBAddress addr, SBType type)
+{
+ SBValue sb_value;
+ lldb::ValueObjectSP new_value_sp;
+ if (IsValid() && name && *name && addr.IsValid() && type.IsValid())
+ {
+ lldb::addr_t address(addr.GetLoadAddress(*this));
+ lldb::TypeImplSP type_impl_sp (type.GetSP());
+ ClangASTType pointer_ast_type(type_impl_sp->GetClangASTType(true).GetPointerType ());
+ if (pointer_ast_type)
+ {
+ lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t)));
+
+ ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false)));
+ ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
+ pointer_ast_type,
+ ConstString(name),
+ buffer,
+ exe_ctx.GetByteOrder(),
+ exe_ctx.GetAddressByteSize()));
+
+ if (ptr_result_valobj_sp)
+ {
+ ptr_result_valobj_sp->GetValue().SetValueType(Value::eValueTypeLoadAddress);
+ Error err;
+ new_value_sp = ptr_result_valobj_sp->Dereference(err);
+ if (new_value_sp)
+ new_value_sp->SetName(ConstString(name));
+ }
+ }
+ }
+ sb_value.SetSP(new_value_sp);
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ {
+ if (new_value_sp)
+ log->Printf ("SBTarget(%p)::CreateValueFromAddress => \"%s\"", m_opaque_sp.get(), new_value_sp->GetName().AsCString());
+ else
+ log->Printf ("SBTarget(%p)::CreateValueFromAddress => NULL", m_opaque_sp.get());
+ }
+ return sb_value;
+}
+
bool
SBTarget::DeleteAllWatchpoints ()
{
@@ -1905,6 +1969,8 @@ SBTarget::AddModule (const char *path,
if (triple)
module_spec.GetArchitecture().SetTriple (triple, target_sp->GetPlatform ().get());
+ else
+ module_spec.GetArchitecture() = target_sp->GetArchitecture();
if (symfile)
module_spec.GetSymbolFileSpec ().SetFile(symfile, false);
diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp
index 2752620c9baf..4b54b1c0c1c6 100644
--- a/source/API/SBThread.cpp
+++ b/source/API/SBThread.cpp
@@ -20,6 +20,7 @@
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/Process.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -507,6 +508,34 @@ SBThread::GetQueueName () const
return name;
}
+lldb::queue_id_t
+SBThread::GetQueueID () const
+{
+ queue_id_t id = LLDB_INVALID_QUEUE_ID;
+ 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()))
+ {
+ id = exe_ctx.GetThreadPtr()->GetQueueID();
+ }
+ else
+ {
+ if (log)
+ log->Printf ("SBThread(%p)::GetQueueID() => error: process is running", exe_ctx.GetThreadPtr());
+ }
+ }
+
+ if (log)
+ log->Printf ("SBThread(%p)::GetQueueID () => 0x%" PRIx64, exe_ctx.GetThreadPtr(), id);
+
+ return id;
+}
+
SBError
SBThread::ResumeNewPlan (ExecutionContext &exe_ctx, ThreadPlan *new_plan)
{
@@ -910,6 +939,31 @@ SBThread::StepOverUntil (lldb::SBFrame &sb_frame,
}
SBError
+SBThread::JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ SBError sb_error;
+
+ Mutex::Locker api_locker;
+ ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
+
+ if (log)
+ log->Printf ("SBThread(%p)::JumpToLine (file+line = %s:%u)", exe_ctx.GetThreadPtr(), file_spec->GetPath().c_str(), line);
+
+ if (!exe_ctx.HasThreadScope())
+ {
+ sb_error.SetErrorString("this SBThread object is invalid");
+ return sb_error;
+ }
+
+ Thread *thread = exe_ctx.GetThreadPtr();
+
+ Error err = thread->JumpToLine (file_spec.get(), line, true);
+ sb_error.SetError (err);
+ return sb_error;
+}
+
+SBError
SBThread::ReturnFromFrame (SBFrame &frame, SBValue &return_value)
{
SBError sb_error;
@@ -1227,3 +1281,38 @@ SBThread::GetDescription (SBStream &description) const
return true;
}
+
+SBThread
+SBThread::GetExtendedBacktrace (const char *type)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ Mutex::Locker api_locker;
+ ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
+ SBThread sb_origin_thread;
+
+ if (exe_ctx.HasThreadScope())
+ {
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
+ {
+ ThreadSP real_thread(exe_ctx.GetThreadPtr());
+ if (real_thread)
+ {
+ ConstString type_const (type);
+ SystemRuntime *runtime = exe_ctx.GetProcessPtr()->GetSystemRuntime();
+ if (runtime)
+ {
+ ThreadSP origin_thread = runtime->GetExtendedBacktrace (real_thread, type_const);
+ sb_origin_thread.SetThread (origin_thread);
+ }
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("SBThread(%p)::GetExtendedBacktrace() => error: process is running", exe_ctx.GetThreadPtr());
+ }
+ }
+
+ return sb_origin_thread;
+}
diff --git a/source/API/SBType.cpp b/source/API/SBType.cpp
index 372d073acf12..3055c2752083 100644
--- a/source/API/SBType.cpp
+++ b/source/API/SBType.cpp
@@ -7,12 +7,6 @@
//
//===----------------------------------------------------------------------===//
-#include <string.h>
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/TemplateBase.h"
-#include "clang/AST/Type.h"
-
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBType.h"
#include "lldb/API/SBStream.h"
@@ -69,8 +63,10 @@ SBType::operator == (SBType &rhs)
if (IsValid() == false)
return !rhs.IsValid();
- return (rhs.m_opaque_sp->GetASTContext() == m_opaque_sp->GetASTContext()) &&
- (rhs.m_opaque_sp->GetOpaqueQualType() == m_opaque_sp->GetOpaqueQualType());
+ if (rhs.IsValid() == false)
+ return false;
+
+ return *m_opaque_sp.get() == *rhs.m_opaque_sp.get();
}
bool
@@ -78,9 +74,11 @@ SBType::operator != (SBType &rhs)
{
if (IsValid() == false)
return rhs.IsValid();
-
- return (rhs.m_opaque_sp->GetASTContext() != m_opaque_sp->GetASTContext()) ||
- (rhs.m_opaque_sp->GetOpaqueQualType() != m_opaque_sp->GetOpaqueQualType());
+
+ if (rhs.IsValid() == false)
+ return true;
+
+ return *m_opaque_sp.get() != *rhs.m_opaque_sp.get();
}
lldb::TypeImplSP
@@ -142,7 +140,7 @@ SBType::GetByteSize()
if (!IsValid())
return 0;
- return m_opaque_sp->GetClangASTType().GetByteSize();
+ return m_opaque_sp->GetClangASTType(false).GetByteSize();
}
@@ -151,7 +149,7 @@ SBType::IsPointerType()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType().IsPointerType();
+ return m_opaque_sp->GetClangASTType(true).IsPointerType();
}
bool
@@ -159,7 +157,7 @@ SBType::IsReferenceType()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType().IsReferenceType();
+ return m_opaque_sp->GetClangASTType(true).IsReferenceType();
}
SBType
@@ -168,7 +166,7 @@ SBType::GetPointerType()
if (!IsValid())
return SBType();
- return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetPointerType()));
+ return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetPointerType())));
}
SBType
@@ -176,7 +174,7 @@ SBType::GetPointeeType()
{
if (!IsValid())
return SBType();
- return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetPointeeType()));
+ return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetPointeeType())));
}
SBType
@@ -184,7 +182,7 @@ SBType::GetReferenceType()
{
if (!IsValid())
return SBType();
- return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetLValueReferenceType()));
+ return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetReferenceType())));
}
SBType
@@ -192,7 +190,7 @@ SBType::GetDereferencedType()
{
if (!IsValid())
return SBType();
- return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetNonReferenceType()));
+ return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetDereferencedType())));
}
bool
@@ -200,7 +198,7 @@ SBType::IsFunctionType ()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType().IsFunctionType();
+ return m_opaque_sp->GetClangASTType(true).IsFunctionType();
}
bool
@@ -208,7 +206,7 @@ SBType::IsPolymorphicClass ()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType().IsPolymorphicClass();
+ return m_opaque_sp->GetClangASTType(true).IsPolymorphicClass();
}
@@ -218,7 +216,7 @@ SBType::GetFunctionReturnType ()
{
if (IsValid())
{
- ClangASTType return_clang_type (m_opaque_sp->GetClangASTType().GetFunctionReturnType());
+ ClangASTType return_clang_type (m_opaque_sp->GetClangASTType(true).GetFunctionReturnType());
if (return_clang_type.IsValid())
return SBType(return_clang_type);
}
@@ -231,13 +229,13 @@ SBType::GetFunctionArgumentTypes ()
SBTypeList sb_type_list;
if (IsValid())
{
- QualType qual_type(QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType()));
- const FunctionProtoType* func = dyn_cast<FunctionProtoType>(qual_type.getTypePtr());
- if (func)
+ ClangASTType func_type(m_opaque_sp->GetClangASTType(true));
+ size_t count = func_type.GetNumberOfFunctionArguments();
+ for (size_t i = 0;
+ i < count;
+ i++)
{
- const uint32_t num_args = func->getNumArgs();
- for (uint32_t i=0; i<num_args; ++i)
- sb_type_list.Append (SBType(ClangASTType(m_opaque_sp->GetASTContext(), func->getArgType(i).getAsOpaquePtr())));
+ sb_type_list.Append(SBType(func_type.GetFunctionArgumentAtIndex(i)));
}
}
return sb_type_list;
@@ -248,14 +246,14 @@ SBType::GetUnqualifiedType()
{
if (!IsValid())
return SBType();
- return SBType(m_opaque_sp->GetClangASTType().GetFullyUnqualifiedType());
+ return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetUnqualifiedType())));
}
lldb::SBType
SBType::GetCanonicalType()
{
if (IsValid())
- return SBType(m_opaque_sp->GetClangASTType().GetCanonicalType());
+ return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetCanonicalType())));
return SBType();
}
@@ -264,7 +262,7 @@ lldb::BasicType
SBType::GetBasicType()
{
if (IsValid())
- return m_opaque_sp->GetClangASTType().GetBasicTypeEnumeration ();
+ return m_opaque_sp->GetClangASTType(false).GetBasicTypeEnumeration ();
return eBasicTypeInvalid;
}
@@ -272,7 +270,7 @@ SBType
SBType::GetBasicType(lldb::BasicType basic_type)
{
if (IsValid())
- return SBType (ClangASTContext::GetBasicType (m_opaque_sp->GetASTContext(), basic_type));
+ return SBType (ClangASTContext::GetBasicType (m_opaque_sp->GetClangASTContext(false), basic_type));
return SBType();
}
@@ -280,7 +278,7 @@ uint32_t
SBType::GetNumberOfDirectBaseClasses ()
{
if (IsValid())
- return m_opaque_sp->GetClangASTType().GetNumDirectBaseClasses();
+ return m_opaque_sp->GetClangASTType(true).GetNumDirectBaseClasses();
return 0;
}
@@ -288,7 +286,7 @@ uint32_t
SBType::GetNumberOfVirtualBaseClasses ()
{
if (IsValid())
- return m_opaque_sp->GetClangASTType().GetNumVirtualBaseClasses();
+ return m_opaque_sp->GetClangASTType(true).GetNumVirtualBaseClasses();
return 0;
}
@@ -296,7 +294,7 @@ uint32_t
SBType::GetNumberOfFields ()
{
if (IsValid())
- return m_opaque_sp->GetClangASTType().GetNumFields();
+ return m_opaque_sp->GetClangASTType(false).GetNumFields();
return 0;
}
@@ -323,7 +321,7 @@ SBType::GetDirectBaseClassAtIndex (uint32_t idx)
SBTypeMember sb_type_member;
if (IsValid())
{
- ClangASTType this_type (m_opaque_sp->GetClangASTType ());
+ ClangASTType this_type (m_opaque_sp->GetClangASTType (true));
if (this_type.IsValid())
{
uint32_t bit_offset = 0;
@@ -344,7 +342,7 @@ SBType::GetVirtualBaseClassAtIndex (uint32_t idx)
SBTypeMember sb_type_member;
if (IsValid())
{
- ClangASTType this_type (m_opaque_sp->GetClangASTType ());
+ ClangASTType this_type (m_opaque_sp->GetClangASTType (true));
if (this_type.IsValid())
{
uint32_t bit_offset = 0;
@@ -364,7 +362,7 @@ SBType::GetFieldAtIndex (uint32_t idx)
SBTypeMember sb_type_member;
if (IsValid())
{
- ClangASTType this_type (m_opaque_sp->GetClangASTType ());
+ ClangASTType this_type (m_opaque_sp->GetClangASTType (false));
if (this_type.IsValid())
{
uint64_t bit_offset = 0;
@@ -397,7 +395,7 @@ SBType::IsTypeComplete()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType().IsCompleteType();
+ return m_opaque_sp->GetClangASTType(false).IsCompleteType();
}
const char*
@@ -405,14 +403,14 @@ SBType::GetName()
{
if (!IsValid())
return "";
- return m_opaque_sp->GetClangASTType().GetConstTypeName().GetCString();
+ return m_opaque_sp->GetName().GetCString();
}
lldb::TypeClass
SBType::GetTypeClass ()
{
if (IsValid())
- return m_opaque_sp->GetClangASTType().GetTypeClass();
+ return m_opaque_sp->GetClangASTType(false).GetTypeClass();
return lldb::eTypeClassInvalid;
}
@@ -420,7 +418,7 @@ uint32_t
SBType::GetNumberOfTemplateArguments ()
{
if (IsValid())
- return m_opaque_sp->GetClangASTType().GetNumTemplateArguments();
+ return m_opaque_sp->GetClangASTType(false).GetNumTemplateArguments();
return 0;
}
@@ -430,7 +428,7 @@ SBType::GetTemplateArgumentType (uint32_t idx)
if (IsValid())
{
TemplateArgumentKind kind = eTemplateArgumentKindNull;
- ClangASTType template_arg_type = m_opaque_sp->GetClangASTType().GetTemplateArgument (idx, kind);
+ ClangASTType template_arg_type = m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind);
if (template_arg_type.IsValid())
return SBType(template_arg_type);
}
@@ -443,7 +441,7 @@ SBType::GetTemplateArgumentKind (uint32_t idx)
{
TemplateArgumentKind kind = eTemplateArgumentKindNull;
if (IsValid())
- m_opaque_sp->GetClangASTType().GetTemplateArgument (idx, kind);
+ m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind);
return kind;
}
diff --git a/source/API/SBTypeCategory.cpp b/source/API/SBTypeCategory.cpp
index e3978693c81c..08fdefad1be8 100644
--- a/source/API/SBTypeCategory.cpp
+++ b/source/API/SBTypeCategory.cpp
@@ -84,10 +84,10 @@ SBTypeCategory::GetName()
uint32_t
SBTypeCategory::GetNumFormats ()
{
- if (!IsDefaultCategory())
+ if (!IsValid())
return 0;
- return DataVisualization::ValueFormats::GetCount();
+ return m_opaque_sp->GetValueNavigator()->GetCount() + m_opaque_sp->GetRegexValueNavigator()->GetCount();
}
uint32_t
@@ -127,9 +127,9 @@ SBTypeCategory::GetTypeNameSpecifierForFilterAtIndex (uint32_t index)
lldb::SBTypeNameSpecifier
SBTypeCategory::GetTypeNameSpecifierForFormatAtIndex (uint32_t index)
{
- if (!IsDefaultCategory())
+ if (!IsValid())
return SBTypeNameSpecifier();
- return SBTypeNameSpecifier(DataVisualization::ValueFormats::GetTypeNameSpecifierForFormatAtIndex(index));
+ return SBTypeNameSpecifier(m_opaque_sp->GetTypeNameSpecifierForFormatAtIndex(index));
}
lldb::SBTypeNameSpecifier
@@ -177,16 +177,23 @@ SBTypeCategory::GetFilterForType (SBTypeNameSpecifier spec)
SBTypeFormat
SBTypeCategory::GetFormatForType (SBTypeNameSpecifier spec)
{
- if (!IsDefaultCategory())
+ if (!IsValid())
return SBTypeFormat();
if (!spec.IsValid())
return SBTypeFormat();
+ lldb::TypeFormatImplSP format_sp;
+
if (spec.IsRegex())
- return SBTypeFormat();
+ m_opaque_sp->GetRegexValueNavigator()->GetExact(ConstString(spec.GetName()), format_sp);
+ else
+ m_opaque_sp->GetValueNavigator()->GetExact(ConstString(spec.GetName()), format_sp);
- return SBTypeFormat(DataVisualization::ValueFormats::GetFormat(ConstString(spec.GetName())));
+ if (!format_sp)
+ return lldb::SBTypeFormat();
+
+ return lldb::SBTypeFormat(format_sp);
}
#ifndef LLDB_DISABLE_PYTHON
@@ -259,9 +266,9 @@ SBTypeCategory::GetFilterAtIndex (uint32_t index)
SBTypeFormat
SBTypeCategory::GetFormatAtIndex (uint32_t index)
{
- if (!IsDefaultCategory())
+ if (!IsValid())
return SBTypeFormat();
- return SBTypeFormat(DataVisualization::ValueFormats::GetFormatAtIndex((index)));
+ return SBTypeFormat(m_opaque_sp->GetFormatAtIndex((index)));
}
#ifndef LLDB_DISABLE_PYTHON
@@ -295,7 +302,7 @@ bool
SBTypeCategory::AddTypeFormat (SBTypeNameSpecifier type_name,
SBTypeFormat format)
{
- if (!IsDefaultCategory())
+ if (!IsValid())
return false;
if (!type_name.IsValid())
@@ -305,9 +312,9 @@ SBTypeCategory::AddTypeFormat (SBTypeNameSpecifier type_name,
return false;
if (type_name.IsRegex())
- return false;
-
- DataVisualization::ValueFormats::Add(ConstString(type_name.GetName()), format.GetSP());
+ m_opaque_sp->GetRegexValueNavigator()->Add(lldb::RegularExpressionSP(new RegularExpression(type_name.GetName())), format.GetSP());
+ else
+ m_opaque_sp->GetValueNavigator()->Add(ConstString(type_name.GetName()), format.GetSP());
return true;
}
@@ -315,16 +322,16 @@ SBTypeCategory::AddTypeFormat (SBTypeNameSpecifier type_name,
bool
SBTypeCategory::DeleteTypeFormat (SBTypeNameSpecifier type_name)
{
- if (!IsDefaultCategory())
+ if (!IsValid())
return false;
if (!type_name.IsValid())
return false;
if (type_name.IsRegex())
- return false;
-
- return DataVisualization::ValueFormats::Delete(ConstString(type_name.GetName()));
+ return m_opaque_sp->GetRegexValueNavigator()->Delete(ConstString(type_name.GetName()));
+ else
+ return m_opaque_sp->GetValueNavigator()->Delete(ConstString(type_name.GetName()));
}
#ifndef LLDB_DISABLE_PYTHON
diff --git a/source/API/SBTypeNameSpecifier.cpp b/source/API/SBTypeNameSpecifier.cpp
index d417499ecbd3..3d03c6a0c539 100644
--- a/source/API/SBTypeNameSpecifier.cpp
+++ b/source/API/SBTypeNameSpecifier.cpp
@@ -36,7 +36,7 @@ SBTypeNameSpecifier::SBTypeNameSpecifier (SBType type) :
m_opaque_sp()
{
if (type.IsValid())
- m_opaque_sp = TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(type.m_opaque_sp->GetClangASTType()));
+ m_opaque_sp = TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(type.m_opaque_sp->GetClangASTType(true)));
}
SBTypeNameSpecifier::SBTypeNameSpecifier (const lldb::SBTypeNameSpecifier &rhs) :
diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp
index aa9b23ac7c69..51b6790dd2b8 100644
--- a/source/API/SBValue.cpp
+++ b/source/API/SBValue.cpp
@@ -63,20 +63,20 @@ public:
lldb::DynamicValueType use_dynamic,
bool use_synthetic,
const char *name = NULL) :
- m_valobj_sp(in_valobj_sp),
- m_use_dynamic(use_dynamic),
- m_use_synthetic(use_synthetic),
- m_name (name)
+ m_valobj_sp(in_valobj_sp),
+ m_use_dynamic(use_dynamic),
+ m_use_synthetic(use_synthetic),
+ m_name (name)
{
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),
- m_use_synthetic(rhs.m_use_synthetic),
- m_name (rhs.m_name)
+ m_valobj_sp(rhs.m_valobj_sp),
+ m_use_dynamic(rhs.m_use_dynamic),
+ m_use_synthetic(rhs.m_use_synthetic),
+ m_name (rhs.m_name)
{
}
@@ -120,7 +120,7 @@ public:
Target *target = value_sp->GetTargetSP().get();
if (target)
api_locker.Lock(target->GetAPIMutex());
-
+
ProcessSP process_sp(value_sp->GetProcessSP());
if (process_sp && !stop_locker.TryLock (&process_sp->GetRunLock()))
{
@@ -131,7 +131,7 @@ public:
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))
@@ -167,7 +167,7 @@ public:
{
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
@@ -207,7 +207,7 @@ public:
else
return StackFrameSP();
}
-
+
private:
lldb::ValueObjectSP m_valobj_sp;
lldb::DynamicValueType m_use_dynamic;
@@ -227,7 +227,7 @@ public:
{
return in_value.GetSP(m_stop_locker, m_api_locker, m_lock_error);
}
-
+
Error &
GetError()
{
@@ -238,11 +238,11 @@ private:
Process::StopLocker m_stop_locker;
Mutex::Locker m_api_locker;
Error m_lock_error;
-
+
};
SBValue::SBValue () :
- m_opaque_sp ()
+m_opaque_sp ()
{
}
@@ -318,7 +318,7 @@ 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)
{
@@ -327,7 +327,7 @@ SBValue::GetName()
else
log->Printf ("SBValue(%p)::GetName () => NULL", value_sp.get());
}
-
+
return name;
}
@@ -350,7 +350,7 @@ SBValue::GetTypeName ()
else
log->Printf ("SBValue(%p)::GetTypeName () => NULL", value_sp.get());
}
-
+
return name;
}
@@ -359,17 +359,17 @@ 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);
-
+
return result;
}
@@ -377,18 +377,18 @@ 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);
-
+
return result;
}
@@ -396,7 +396,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));
@@ -411,7 +411,7 @@ SBValue::GetValue ()
else
log->Printf ("SBValue(%p)::GetValue() => NULL", value_sp.get());
}
-
+
return cstr;
}
@@ -429,14 +429,14 @@ SBValue::GetValueType ()
{
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", 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;
}
}
return result;
@@ -473,7 +473,7 @@ SBValue::GetType()
TypeImplSP type_sp;
if (value_sp)
{
- type_sp.reset (new TypeImpl(value_sp->GetClangType()));
+ type_sp.reset (new TypeImpl(value_sp->GetTypeImpl()));
sb_type.SetSP(type_sp);
}
if (log)
@@ -499,7 +499,7 @@ SBValue::GetValueDidChange ()
}
if (log)
log->Printf ("SBValue(%p)::GetValueDidChange() => %i", value_sp.get(), result);
-
+
return result;
}
@@ -571,7 +571,7 @@ SBValue::SetValueFromCString (const char *value_str, lldb::SBError& error)
if (log)
log->Printf ("SBValue(%p)::SetValueFromCString(\"%s\") => %i", value_sp.get(), value_str, success);
-
+
return success;
}
@@ -671,7 +671,7 @@ SBValue::CreateChildAtOffset (const char *name, uint32_t offset, SBType type)
TypeImplSP type_sp (type.GetSP());
if (type.IsValid())
{
- sb_value.SetSP(value_sp->GetSyntheticChildAtOffset(offset, type_sp->GetClangASTType(), true),GetPreferDynamicValue(),GetPreferSyntheticValue(), name);
+ sb_value.SetSP(value_sp->GetSyntheticChildAtOffset(offset, type_sp->GetClangASTType(false), true),GetPreferDynamicValue(),GetPreferSyntheticValue(), name);
}
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -696,7 +696,7 @@ SBValue::Cast (SBType type)
lldb::ValueObjectSP value_sp(GetSP(locker));
TypeImplSP type_sp (type.GetSP());
if (value_sp && type_sp)
- sb_value.SetSP(value_sp->Cast(type_sp->GetClangASTType()),GetPreferDynamicValue(),GetPreferSyntheticValue());
+ sb_value.SetSP(value_sp->Cast(type_sp->GetClangASTType(false)),GetPreferDynamicValue(),GetPreferSyntheticValue());
return sb_value;
}
@@ -761,19 +761,19 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, SBType s
lldb::TypeImplSP type_impl_sp (sb_type.GetSP());
if (value_sp && type_impl_sp)
{
- ClangASTType pointee_ast_type(type_impl_sp->GetClangASTType().GetPointerType ());
- if (pointee_ast_type)
+ ClangASTType pointer_ast_type(type_impl_sp->GetClangASTType(false).GetPointerType ());
+ if (pointer_ast_type)
{
lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t)));
-
+
ExecutionContext exe_ctx (value_sp->GetExecutionContextRef());
ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
- pointee_ast_type,
+ pointer_ast_type,
ConstString(name),
buffer,
- lldb::endian::InlHostByteOrder(),
+ exe_ctx.GetByteOrder(),
exe_ctx.GetAddressByteSize()));
-
+
if (ptr_result_valobj_sp)
{
ptr_result_valobj_sp->GetValue().SetValueType(Value::eValueTypeLoadAddress);
@@ -806,9 +806,9 @@ 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(),
+ type.m_opaque_sp->GetClangASTType(false),
ConstString(name),
*data.m_opaque_sp,
LLDB_INVALID_ADDRESS);
@@ -837,7 +837,7 @@ SBValue::GetChildAtIndex (uint32_t idx)
if (target_sp)
use_dynamic = target_sp->GetPreferDynamicValue();
-
+
return GetChildAtIndex (idx, use_dynamic, can_create_synthetic);
}
@@ -846,7 +846,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)
@@ -870,7 +870,7 @@ SBValue::GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic, bool
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());
-
+
return sb_value;
}
@@ -913,9 +913,9 @@ 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)
@@ -925,10 +925,10 @@ SBValue::GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dy
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());
-
+
return sb_value;
}
@@ -1048,11 +1048,12 @@ SBValue::GetValueAsSigned(SBError& error, int64_t fail_value)
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
{
- Scalar scalar;
- if (value_sp->ResolveValue (scalar))
- return scalar.SLongLong (fail_value);
- else
- error.SetErrorString ("could not resolve value");
+ bool success = true;
+ uint64_t ret_val = fail_value;
+ ret_val = value_sp->GetValueAsSigned(fail_value, &success);
+ if (!success)
+ error.SetErrorString("could not resolve value");
+ return ret_val;
}
else
error.SetErrorStringWithFormat ("could not get SBValue: %s", locker.GetError().AsCString());
@@ -1068,11 +1069,12 @@ SBValue::GetValueAsUnsigned(SBError& error, uint64_t fail_value)
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
{
- Scalar scalar;
- if (value_sp->ResolveValue (scalar))
- return scalar.ULongLong(fail_value);
- else
+ bool success = true;
+ uint64_t ret_val = fail_value;
+ ret_val = value_sp->GetValueAsUnsigned(fail_value, &success);
+ if (!success)
error.SetErrorString("could not resolve value");
+ return ret_val;
}
else
error.SetErrorStringWithFormat ("could not get SBValue: %s", locker.GetError().AsCString());
@@ -1087,9 +1089,7 @@ SBValue::GetValueAsSigned(int64_t fail_value)
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
{
- Scalar scalar;
- if (value_sp->ResolveValue (scalar))
- return scalar.SLongLong(fail_value);
+ return value_sp->GetValueAsSigned(fail_value);
}
return fail_value;
}
@@ -1101,9 +1101,7 @@ SBValue::GetValueAsUnsigned(uint64_t fail_value)
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
{
- Scalar scalar;
- if (value_sp->ResolveValue (scalar))
- return scalar.ULongLong(fail_value);
+ return value_sp->GetValueAsUnsigned(fail_value);
}
return fail_value;
}
@@ -1117,7 +1115,7 @@ 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);
return has_children;
@@ -1127,16 +1125,16 @@ 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);
-
+
return num_children;
}
@@ -1149,13 +1147,13 @@ SBValue::Dereference ()
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
{
- Error error;
- sb_value = value_sp->Dereference (error);
+ Error error;
+ sb_value = value_sp->Dereference (error);
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
log->Printf ("SBValue(%p)::Dereference () => SBValue(%p)", value_sp.get(), value_sp.get());
-
+
return sb_value;
}
@@ -1163,17 +1161,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);
-
-
+
+
return is_ptr_type;
}
@@ -1390,16 +1388,14 @@ bool
SBValue::GetDescription (SBStream &description)
{
Stream &strm = description.ref();
-
+
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
- {
- ValueObject::DumpValueObject (strm, value_sp.get());
- }
+ value_sp->Dump(strm);
else
strm.PutCString ("No value");
-
+
return true;
}
@@ -1653,7 +1649,7 @@ SBValue::Watch (bool resolve_location, bool read, bool write, SBError &error)
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;
@@ -1664,14 +1660,14 @@ SBValue::Watch (bool resolve_location, bool read, bool write, SBError &error)
ClangASTType type (value_sp->GetClangType());
WatchpointSP watchpoint_sp = target_sp->CreateWatchpoint(addr, byte_size, &type, watch_type, rc);
error.SetError(rc);
-
- if (watchpoint_sp)
+
+ if (watchpoint_sp)
{
sb_watchpoint.SetSP (watchpoint_sp);
Declaration decl;
if (value_sp->GetDeclaration (decl))
{
- if (decl.GetFile())
+ if (decl.GetFile())
{
StreamString ss;
// True to show fullpath for declaration file.
diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp
index 9bc43814b48a..e07205e360b1 100644
--- a/source/Breakpoint/Breakpoint.cpp
+++ b/source/Breakpoint/Breakpoint.cpp
@@ -45,8 +45,9 @@ Breakpoint::GetEventIdentifier ()
//----------------------------------------------------------------------
// Breakpoint constructor
//----------------------------------------------------------------------
-Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp) :
+Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool hardware) :
m_being_created(true),
+ m_hardware(hardware),
m_target (target),
m_filter_sp (filter_sp),
m_resolver_sp (resolver_sp),
@@ -558,7 +559,7 @@ Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_l
{
s->Printf(", locations = %" PRIu64, (uint64_t)num_locations);
if (num_resolved_locations > 0)
- s->Printf(", resolved = %" PRIu64, (uint64_t)num_resolved_locations);
+ s->Printf(", resolved = %" PRIu64 ", hit count = %d", (uint64_t)num_resolved_locations, GetHitCount());
}
else
{
diff --git a/source/Breakpoint/BreakpointList.cpp b/source/Breakpoint/BreakpointList.cpp
index 5926663af7b1..c6030d60ca04 100644
--- a/source/Breakpoint/BreakpointList.cpp
+++ b/source/Breakpoint/BreakpointList.cpp
@@ -204,13 +204,13 @@ BreakpointList::GetBreakpointAtIndex (size_t i) const
}
void
-BreakpointList::UpdateBreakpoints (ModuleList& module_list, bool added)
+BreakpointList::UpdateBreakpoints (ModuleList& module_list, bool added, bool delete_locations)
{
Mutex::Locker locker(m_mutex);
bp_collection::iterator end = m_breakpoints.end();
bp_collection::iterator pos;
for (pos = m_breakpoints.begin(); pos != end; ++pos)
- (*pos)->ModulesChanged (module_list, added);
+ (*pos)->ModulesChanged (module_list, added, delete_locations);
}
diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp
index 1ec726dd52b1..17568c28b507 100644
--- a/source/Breakpoint/BreakpointLocation.cpp
+++ b/source/Breakpoint/BreakpointLocation.cpp
@@ -291,9 +291,11 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
// constructor errors up to the debugger's Async I/O.
ValueObjectSP result_value_sp;
- const bool unwind_on_error = true;
- const bool ignore_breakpoints = true;
- const bool try_all_threads = true;
+
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetRunOthers(true);
Error expr_error;
@@ -304,12 +306,9 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
ExecutionResults result_code =
m_user_expression_sp->Execute(execution_errors,
exe_ctx,
- unwind_on_error,
- ignore_breakpoints,
+ options,
m_user_expression_sp,
- result_variable_sp,
- try_all_threads,
- ClangUserExpression::kDefaultTimeout);
+ result_variable_sp);
bool ret;
@@ -484,7 +483,7 @@ BreakpointLocation::ResolveBreakpointSite ()
if (process == NULL)
return false;
- lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), false);
+ lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), m_owner.IsHardware());
if (new_id == LLDB_INVALID_BREAK_ID)
{
diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp
index 22a4ff0c68ee..341b09716301 100644
--- a/source/Breakpoint/BreakpointLocationList.cpp
+++ b/source/Breakpoint/BreakpointLocationList.cpp
@@ -41,7 +41,7 @@ BreakpointLocationList::Create (const Address &addr)
Mutex::Locker locker (m_mutex);
// The location ID is just the size of the location list + 1
lldb::break_id_t bp_loc_id = ++m_next_id;
- BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr));
+ BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware()));
m_locations.push_back (bp_loc_sp);
m_address_to_location[addr] = bp_loc_sp;
return bp_loc_sp;
diff --git a/source/Breakpoint/BreakpointResolver.cpp b/source/Breakpoint/BreakpointResolver.cpp
index b22fa1e6dbcc..33b0ff40e35f 100644
--- a/source/Breakpoint/BreakpointResolver.cpp
+++ b/source/Breakpoint/BreakpointResolver.cpp
@@ -23,9 +23,12 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Target.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
#include "lldb/lldb-private-log.h"
using namespace lldb_private;
+using namespace lldb;
//----------------------------------------------------------------------
// BreakpointResolver:
@@ -59,3 +62,144 @@ BreakpointResolver::ResolveBreakpoint (SearchFilter &filter)
filter.Search (*this);
}
+void
+BreakpointResolver::SetSCMatchesByLine (SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, const char *log_ident)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+
+ while (sc_list.GetSize() > 0)
+ {
+ SymbolContextList tmp_sc_list;
+ unsigned current_idx = 0;
+ SymbolContext sc;
+ bool first_entry = true;
+
+ FileSpec match_file_spec;
+ uint32_t closest_line_number = UINT32_MAX;
+
+ // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list.
+ while (current_idx < sc_list.GetSize())
+ {
+ bool matches;
+
+ sc_list.GetContextAtIndex (current_idx, sc);
+ if (first_entry)
+ {
+ match_file_spec = sc.line_entry.file;
+ matches = true;
+ first_entry = false;
+ }
+ else
+ matches = (sc.line_entry.file == match_file_spec);
+
+ if (matches)
+ {
+ tmp_sc_list.Append (sc);
+ sc_list.RemoveContextAtIndex(current_idx);
+
+ // ResolveSymbolContext will always return a number that is >= the line number you pass in.
+ // So the smaller line number is always better.
+ if (sc.line_entry.line < closest_line_number)
+ closest_line_number = sc.line_entry.line;
+ }
+ else
+ current_idx++;
+ }
+
+ // Okay, we've found the closest line number match, now throw away all the others:
+
+ current_idx = 0;
+ while (current_idx < tmp_sc_list.GetSize())
+ {
+ if (tmp_sc_list.GetContextAtIndex(current_idx, sc))
+ {
+ if (sc.line_entry.line != closest_line_number)
+ tmp_sc_list.RemoveContextAtIndex(current_idx);
+ else
+ current_idx++;
+ }
+ }
+
+ // Next go through and see if there are line table entries that are contiguous, and if so keep only the
+ // first of the contiguous range:
+
+ current_idx = 0;
+ std::map<Block *, lldb::addr_t> blocks_with_breakpoints;
+
+ while (current_idx < tmp_sc_list.GetSize())
+ {
+ if (tmp_sc_list.GetContextAtIndex(current_idx, sc))
+ {
+ if (blocks_with_breakpoints.find (sc.block) != blocks_with_breakpoints.end())
+ tmp_sc_list.RemoveContextAtIndex(current_idx);
+ else
+ {
+ blocks_with_breakpoints.insert (std::pair<Block *, lldb::addr_t>(sc.block, sc.line_entry.range.GetBaseAddress().GetFileAddress()));
+ current_idx++;
+ }
+ }
+ }
+
+ // and make breakpoints out of the closest line number match.
+
+ uint32_t tmp_sc_list_size = tmp_sc_list.GetSize();
+
+ for (uint32_t i = 0; i < tmp_sc_list_size; i++)
+ {
+ if (tmp_sc_list.GetContextAtIndex(i, sc))
+ {
+ Address line_start = sc.line_entry.range.GetBaseAddress();
+ if (line_start.IsValid())
+ {
+ if (filter.AddressPasses(line_start))
+ {
+ // If the line number is before the prologue end, move it there...
+ bool skipped_prologue = false;
+ if (skip_prologue)
+ {
+ if (sc.function)
+ {
+ Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress());
+ if (prologue_addr.IsValid() && (line_start == prologue_addr))
+ {
+ const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
+ if (prologue_byte_size)
+ {
+ prologue_addr.Slide(prologue_byte_size);
+
+ if (filter.AddressPasses(prologue_addr))
+ {
+ skipped_prologue = true;
+ line_start = prologue_addr;
+ }
+ }
+ }
+ }
+ }
+
+ BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
+ if (log && bp_loc_sp && !m_breakpoint->IsInternal())
+ {
+ StreamString s;
+ bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
+ log->Printf ("Added location (skipped prologue: %s): %s \n", skipped_prologue ? "yes" : "no", s.GetData());
+ }
+ }
+ else if (log)
+ {
+ log->Printf ("Breakpoint %s at file address 0x%" PRIx64 " didn't pass the filter.\n",
+ log_ident ? log_ident : "",
+ line_start.GetFileAddress());
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("error: Unable to set breakpoint %s at file address 0x%" PRIx64 "\n",
+ log_ident ? log_ident : "",
+ line_start.GetFileAddress());
+ }
+ }
+ }
+ }
+}
diff --git a/source/Breakpoint/BreakpointResolverFileLine.cpp b/source/Breakpoint/BreakpointResolverFileLine.cpp
index 91a218fdb80a..dcee2fd54125 100644
--- a/source/Breakpoint/BreakpointResolverFileLine.cpp
+++ b/source/Breakpoint/BreakpointResolverFileLine.cpp
@@ -59,7 +59,6 @@ BreakpointResolverFileLine::SearchCallback
SymbolContextList sc_list;
assert (m_breakpoint != NULL);
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
// There is a tricky bit here. You can have two compilation units that #include the same file, and
// in one of them the function at m_line_number is used (and so code and a line entry for it is generated) but in the
@@ -83,146 +82,13 @@ BreakpointResolverFileLine::SearchCallback
cu_sp->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything, sc_list);
}
}
-
- while (sc_list.GetSize() > 0)
- {
- SymbolContextList tmp_sc_list;
- unsigned current_idx = 0;
- SymbolContext sc;
- bool first_entry = true;
-
- FileSpec match_file_spec;
- uint32_t closest_line_number = UINT32_MAX;
+ StreamString s;
+ s.Printf ("for %s:%d ",
+ m_file_spec.GetFilename().AsCString("<Unknown>"),
+ m_line_number);
- // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list.
- while (current_idx < sc_list.GetSize())
- {
- bool matches;
-
- sc_list.GetContextAtIndex (current_idx, sc);
- if (first_entry)
- {
- match_file_spec = sc.line_entry.file;
- matches = true;
- first_entry = false;
- }
- else
- matches = (sc.line_entry.file == match_file_spec);
-
- if (matches)
- {
- tmp_sc_list.Append (sc);
- sc_list.RemoveContextAtIndex(current_idx);
-
- // ResolveSymbolContext will always return a number that is >= the line number you pass in.
- // So the smaller line number is always better.
- if (sc.line_entry.line < closest_line_number)
- closest_line_number = sc.line_entry.line;
- }
- else
- current_idx++;
- }
-
- // Okay, we've found the closest line number match, now throw away all the others:
-
- current_idx = 0;
- while (current_idx < tmp_sc_list.GetSize())
- {
- if (tmp_sc_list.GetContextAtIndex(current_idx, sc))
- {
- if (sc.line_entry.line != closest_line_number)
- tmp_sc_list.RemoveContextAtIndex(current_idx);
- else
- current_idx++;
- }
- }
-
- // Next go through and see if there are line table entries that are contiguous, and if so keep only the
- // first of the contiguous range:
-
- lldb::addr_t last_end_addr = LLDB_INVALID_ADDRESS;
- current_idx = 0;
- while (current_idx < tmp_sc_list.GetSize())
- {
- if (tmp_sc_list.GetContextAtIndex(current_idx, sc))
- {
- lldb::addr_t start_file_addr = sc.line_entry.range.GetBaseAddress().GetFileAddress();
- lldb::addr_t end_file_addr = start_file_addr + sc.line_entry.range.GetByteSize();
-
- if (start_file_addr == last_end_addr)
- tmp_sc_list.RemoveContextAtIndex(current_idx);
- else
- current_idx++;
+ SetSCMatchesByLine (filter, sc_list, m_skip_prologue, s.GetData());
- last_end_addr = end_file_addr;
- }
- }
-
- // and make breakpoints out of the closest line number match.
-
- uint32_t tmp_sc_list_size = tmp_sc_list.GetSize();
-
- for (uint32_t i = 0; i < tmp_sc_list_size; i++)
- {
- if (tmp_sc_list.GetContextAtIndex(i, sc))
- {
- Address line_start = sc.line_entry.range.GetBaseAddress();
- if (line_start.IsValid())
- {
- if (filter.AddressPasses(line_start))
- {
- // If the line number is before the prologue end, move it there...
- bool skipped_prologue = false;
- if (m_skip_prologue)
- {
- if (sc.function)
- {
- Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress());
- if (prologue_addr.IsValid() && (line_start == prologue_addr))
- {
- const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
- if (prologue_byte_size)
- {
- prologue_addr.Slide(prologue_byte_size);
-
- if (filter.AddressPasses(prologue_addr))
- {
- skipped_prologue = true;
- line_start = prologue_addr;
- }
- }
- }
- }
- }
-
- BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
- if (log && bp_loc_sp && !m_breakpoint->IsInternal())
- {
- StreamString s;
- bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
- log->Printf ("Added location (skipped prologue: %s): %s \n", skipped_prologue ? "yes" : "no", s.GetData());
- }
- }
- else if (log)
- {
- log->Printf ("Breakpoint at file address 0x%" PRIx64 " for %s:%d didn't pass the filter.\n",
- line_start.GetFileAddress(),
- m_file_spec.GetFilename().AsCString("<Unknown>"),
- m_line_number);
- }
- }
- else
- {
- if (log)
- log->Printf ("error: Unable to set breakpoint at file address 0x%" PRIx64 " for %s:%d\n",
- line_start.GetFileAddress(),
- m_file_spec.GetFilename().AsCString("<Unknown>"),
- m_line_number);
- }
- }
- }
- }
-
return Searcher::eCallbackReturnContinue;
}
diff --git a/source/Breakpoint/BreakpointResolverFileRegex.cpp b/source/Breakpoint/BreakpointResolverFileRegex.cpp
index de974d04894a..01aecee7b9c2 100644
--- a/source/Breakpoint/BreakpointResolverFileRegex.cpp
+++ b/source/Breakpoint/BreakpointResolverFileRegex.cpp
@@ -54,60 +54,23 @@ BreakpointResolverFileRegex::SearchCallback
assert (m_breakpoint != NULL);
if (!context.target_sp)
return eCallbackReturnContinue;
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
CompileUnit *cu = context.comp_unit;
FileSpec cu_file_spec = *(static_cast<FileSpec *>(cu));
std::vector<uint32_t> line_matches;
- context.target_sp->GetSourceManager().FindLinesMatchingRegex(cu_file_spec, m_regex, 1, UINT32_MAX, line_matches);
+ context.target_sp->GetSourceManager().FindLinesMatchingRegex(cu_file_spec, m_regex, 1, UINT32_MAX, line_matches);
+
uint32_t num_matches = line_matches.size();
for (uint32_t i = 0; i < num_matches; i++)
{
- uint32_t start_idx = 0;
- bool exact = false;
- while (1)
- {
- LineEntry line_entry;
+ SymbolContextList sc_list;
+ const bool search_inlines = false;
+ const bool exact = false;
- // Cycle through all the line entries that might match this one:
- start_idx = cu->FindLineEntry (start_idx, line_matches[i], NULL, exact, &line_entry);
- if (start_idx == UINT32_MAX)
- break;
- exact = true;
- start_idx++;
-
- Address line_start = line_entry.range.GetBaseAddress();
- if (line_start.IsValid())
- {
- if (filter.AddressPasses(line_start))
- {
- BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
- if (log && bp_loc_sp && !m_breakpoint->IsInternal())
- {
- StreamString s;
- bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
- log->Printf ("Added location: %s\n", s.GetData());
- }
- }
- else if (log)
- {
- log->Printf ("Breakpoint at file address 0x%" PRIx64 " for %s:%d didn't pass filter.\n",
- line_start.GetFileAddress(),
- cu_file_spec.GetFilename().AsCString("<Unknown>"),
- line_matches[i]);
- }
- }
- else
- {
- if (log)
- log->Printf ("error: Unable to set breakpoint at file address 0x%" PRIx64 " for %s:%d\n",
- line_start.GetFileAddress(),
- cu_file_spec.GetFilename().AsCString("<Unknown>"),
- line_matches[i]);
- }
-
- }
+ cu->ResolveSymbolContext (cu_file_spec, line_matches[i], search_inlines, exact, eSymbolContextEverything, sc_list);
+ const bool skip_prologue = true;
+
+ BreakpointResolver::SetSCMatchesByLine (filter, sc_list, skip_prologue, m_regex.GetText());
}
assert (m_breakpoint != NULL);
diff --git a/source/Breakpoint/BreakpointResolverName.cpp b/source/Breakpoint/BreakpointResolverName.cpp
index 27f85653d648..c82dd5ee050b 100644
--- a/source/Breakpoint/BreakpointResolverName.cpp
+++ b/source/Breakpoint/BreakpointResolverName.cpp
@@ -289,7 +289,17 @@ BreakpointResolverName::SearchCallback
}
else if (sc.symbol)
{
- break_addr = sc.symbol->GetAddress();
+ if (sc.symbol->GetType() == eSymbolTypeReExported)
+ {
+ const Symbol *actual_symbol = sc.symbol->ResolveReExportedSymbol(m_breakpoint->GetTarget());
+ if (actual_symbol)
+ break_addr = actual_symbol->GetAddress();
+ }
+ else
+ {
+ break_addr = sc.symbol->GetAddress();
+ }
+
if (m_skip_prologue && break_addr.IsValid())
{
const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
diff --git a/source/Breakpoint/StoppointLocation.cpp b/source/Breakpoint/StoppointLocation.cpp
index 092caa5a9322..9d8d9241253a 100644
--- a/source/Breakpoint/StoppointLocation.cpp
+++ b/source/Breakpoint/StoppointLocation.cpp
@@ -23,8 +23,8 @@ using namespace lldb_private;
StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, bool hardware) :
m_loc_id(bid),
m_addr(addr),
- m_hw_preferred(hardware),
- m_hw_index(LLDB_INVALID_INDEX32),
+ m_hardware(hardware),
+ m_hardware_index(LLDB_INVALID_INDEX32),
m_byte_size(0),
m_hit_count(0)
{
@@ -33,8 +33,8 @@ StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, bool hardware
StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, uint32_t byte_size, bool hardware) :
m_loc_id(bid),
m_addr(addr),
- m_hw_preferred(hardware),
- m_hw_index(LLDB_INVALID_INDEX32),
+ m_hardware(hardware),
+ m_hardware_index(LLDB_INVALID_INDEX32),
m_byte_size(byte_size),
m_hit_count(0)
{
diff --git a/source/Commands/CommandCompletions.cpp b/source/Commands/CommandCompletions.cpp
index a9d2f21b9bac..970aa692bd27 100644
--- a/source/Commands/CommandCompletions.cpp
+++ b/source/Commands/CommandCompletions.cpp
@@ -11,7 +11,6 @@
// C Includes
#include <sys/stat.h>
-#include <dirent.h>
#if defined(__APPLE__) || defined(__linux__)
#include <pwd.h>
#endif
@@ -121,6 +120,71 @@ CommandCompletions::SourceFiles
return matches.GetSize();
}
+typedef struct DiskFilesOrDirectoriesBaton
+{
+ const char *remainder;
+ char *partial_name_copy;
+ bool only_directories;
+ bool *saw_directory;
+ StringList *matches;
+ char *end_ptr;
+ size_t baselen;
+} DiskFilesOrDirectoriesBaton;
+
+FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec)
+{
+ const char *name = spec.GetFilename().AsCString();
+
+ const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton;
+ char *end_ptr = parameters->end_ptr;
+ char *partial_name_copy = parameters->partial_name_copy;
+ const char *remainder = parameters->remainder;
+
+ // Omit ".", ".." and any . files if the match string doesn't start with .
+ if (name[0] == '.')
+ {
+ if (name[1] == '\0')
+ return FileSpec::eEnumerateDirectoryResultNext;
+ else if (name[1] == '.' && name[2] == '\0')
+ return FileSpec::eEnumerateDirectoryResultNext;
+ else if (remainder[0] != '.')
+ return FileSpec::eEnumerateDirectoryResultNext;
+ }
+
+ // If we found a directory, we put a "/" at the end of the name.
+
+ if (remainder[0] == '\0' || strstr(name, remainder) == name)
+ {
+ if (strlen(name) + parameters->baselen >= PATH_MAX)
+ return FileSpec::eEnumerateDirectoryResultNext;
+
+ strcpy(end_ptr, name);
+
+ bool isa_directory = false;
+ if (file_type == FileSpec::eFileTypeDirectory)
+ isa_directory = true;
+ else if (file_type == FileSpec::eFileTypeSymbolicLink)
+ {
+ struct stat stat_buf;
+ if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
+ isa_directory = true;
+ }
+
+ if (isa_directory)
+ {
+ *parameters->saw_directory = true;
+ size_t len = strlen(parameters->partial_name_copy);
+ partial_name_copy[len] = '/';
+ partial_name_copy[len + 1] = '\0';
+ }
+ if (parameters->only_directories && !isa_directory)
+ return FileSpec::eEnumerateDirectoryResultNext;
+ parameters->matches->AppendString(partial_name_copy);
+ }
+
+ return FileSpec::eEnumerateDirectoryResultNext;
+}
+
static int
DiskFilesOrDirectories
(
@@ -239,60 +303,18 @@ DiskFilesOrDirectories
// Okay, containing_part is now the directory we want to open and look for files:
- lldb_utility::CleanUp <DIR *, int> dir_stream (opendir(containing_part), NULL, closedir);
- if (!dir_stream.is_valid())
- return matches.GetSize();
-
- struct dirent *dirent_buf;
-
size_t baselen = end_ptr - partial_name_copy;
- while ((dirent_buf = readdir(dir_stream.get())) != NULL)
- {
- char *name = dirent_buf->d_name;
-
- // Omit ".", ".." and any . files if the match string doesn't start with .
- if (name[0] == '.')
- {
- if (name[1] == '\0')
- continue;
- else if (name[1] == '.' && name[2] == '\0')
- continue;
- else if (remainder[0] != '.')
- continue;
- }
-
- // If we found a directory, we put a "/" at the end of the name.
-
- if (remainder[0] == '\0' || strstr(dirent_buf->d_name, remainder) == name)
- {
- if (strlen(name) + baselen >= PATH_MAX)
- continue;
-
- strcpy(end_ptr, name);
-
- bool isa_directory = false;
- if (dirent_buf->d_type & DT_DIR)
- isa_directory = true;
- else if (dirent_buf->d_type & DT_LNK)
- {
- struct stat stat_buf;
- if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
- isa_directory = true;
- }
-
- if (isa_directory)
- {
- saw_directory = true;
- size_t len = strlen(partial_name_copy);
- partial_name_copy[len] = '/';
- partial_name_copy[len + 1] = '\0';
- }
- if (only_directories && !isa_directory)
- continue;
- matches.AppendString(partial_name_copy);
- }
- }
+ DiskFilesOrDirectoriesBaton parameters;
+ parameters.remainder = remainder;
+ parameters.partial_name_copy = partial_name_copy;
+ parameters.only_directories = only_directories;
+ parameters.saw_directory = &saw_directory;
+ parameters.matches = &matches;
+ parameters.end_ptr = end_ptr;
+ parameters.baselen = baselen;
+
+ FileSpec::EnumerateDirectory(containing_part, true, true, true, DiskFilesOrDirectoriesCallback, &parameters);
return matches.GetSize();
}
diff --git a/source/Commands/CommandObjectArgs.cpp b/source/Commands/CommandObjectArgs.cpp
index 05fd53bbe89a..3b919d11a566 100644
--- a/source/Commands/CommandObjectArgs.cpp
+++ b/source/Commands/CommandObjectArgs.cpp
@@ -266,7 +266,7 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
OptionDefinition
CommandObjectArgs::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."},
+ { 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 }
};
diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp
index cb70c99a1955..c20da7f3ec5c 100644
--- a/source/Commands/CommandObjectBreakpoint.cpp
+++ b/source/Commands/CommandObjectBreakpoint.cpp
@@ -106,6 +106,7 @@ public:
m_queue_name(),
m_catch_bp (false),
m_throw_bp (true),
+ m_hardware (false),
m_language (eLanguageTypeUnknown),
m_skip_prologue (eLazyBoolCalculate),
m_one_shot (false)
@@ -183,13 +184,18 @@ public:
break;
case 'h':
- {
- bool success;
- m_catch_bp = Args::StringToBoolean (option_arg, true, &success);
- if (!success)
- error.SetErrorStringWithFormat ("Invalid boolean value for on-catch option: '%s'", option_arg);
- }
- break;
+ {
+ bool success;
+ m_catch_bp = Args::StringToBoolean (option_arg, true, &success);
+ if (!success)
+ error.SetErrorStringWithFormat ("Invalid boolean value for on-catch option: '%s'", option_arg);
+ }
+ break;
+
+ case 'H':
+ m_hardware = true;
+ break;
+
case 'i':
{
m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
@@ -311,6 +317,7 @@ public:
m_queue_name.clear();
m_catch_bp = false;
m_throw_bp = true;
+ m_hardware = false;
m_language = eLanguageTypeUnknown;
m_skip_prologue = eLazyBoolCalculate;
m_one_shot = false;
@@ -345,6 +352,7 @@ public:
std::string m_queue_name;
bool m_catch_bp;
bool m_throw_bp;
+ bool m_hardware; // Request to use hardware breakpoints
lldb::LanguageType m_language;
LazyBool m_skip_prologue;
bool m_one_shot;
@@ -423,12 +431,15 @@ protected:
m_options.m_line_num,
check_inlines,
m_options.m_skip_prologue,
- internal).get();
+ internal,
+ m_options.m_hardware).get();
}
break;
case eSetTypeAddress: // Breakpoint by address
- bp = target->CreateBreakpoint (m_options.m_load_addr, false).get();
+ bp = target->CreateBreakpoint (m_options.m_load_addr,
+ internal,
+ m_options.m_hardware).get();
break;
case eSetTypeFunctionName: // Breakpoint by function name
@@ -443,7 +454,8 @@ protected:
m_options.m_func_names,
name_type_mask,
m_options.m_skip_prologue,
- internal).get();
+ internal,
+ m_options.m_hardware).get();
}
break;
@@ -464,7 +476,8 @@ protected:
&(m_options.m_filenames),
regexp,
m_options.m_skip_prologue,
- internal).get();
+ internal,
+ m_options.m_hardware).get();
}
break;
case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
@@ -496,12 +509,19 @@ protected:
result.SetStatus (eReturnStatusFailed);
return false;
}
- bp = target->CreateSourceRegexBreakpoint (&(m_options.m_modules), &(m_options.m_filenames), regexp).get();
+ bp = target->CreateSourceRegexBreakpoint (&(m_options.m_modules),
+ &(m_options.m_filenames),
+ regexp,
+ internal,
+ m_options.m_hardware).get();
}
break;
case eSetTypeException:
{
- bp = target->CreateExceptionBreakpoint (m_options.m_language, m_options.m_catch_bp, m_options.m_throw_bp).get();
+ bp = target->CreateExceptionBreakpoint (m_options.m_language,
+ m_options.m_catch_bp,
+ m_options.m_throw_bp,
+ m_options.m_hardware).get();
}
break;
default:
@@ -603,84 +623,87 @@ private:
OptionDefinition
CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_NOT_10, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
+ { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeCount,
+ { 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', no_argument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
"The breakpoint is deleted the first time it causes a stop." },
- { LLDB_OPT_SET_ALL, false, "condition", 'c', required_argument, NULL, 0, eArgTypeExpression,
+ { 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_ALL, false, "thread-index", 'x', required_argument, NULL, 0, eArgTypeThreadIndex,
+ { 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', required_argument, NULL, 0, eArgTypeThreadID,
+ { 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', required_argument, NULL, 0, eArgTypeThreadName,
+ { 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', required_argument, NULL, 0, eArgTypeQueueName,
+ { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
+ "Require the breakpoint to use hardware breakpoints."},
+
+ { 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_FILE, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
+ { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeLineNum,
+ { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, 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.
// This way users won't see it, but the infrastructure is left in place.
- // { 0, false, "column", 'C', required_argument, NULL, "<column>",
+ // { 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', required_argument, NULL, 0, eArgTypeAddressOrExpression,
+ { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression,
"Set the breakpoint by address, at the specified address."},
- { LLDB_OPT_SET_3, true, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
+ { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, 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', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName,
+ { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeSelector,
+ { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeMethod,
+ { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeRegularExpression,
+ { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, 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', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
+ { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeRegularExpression,
+ { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeLanguage,
+ { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeBoolean,
+ { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
"Set the breakpoint on exception throW." },
- { LLDB_OPT_SET_10, false, "on-catch", 'h', required_argument, NULL, 0, eArgTypeBoolean,
+ { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
"Set the breakpoint on exception catcH." },
- { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', required_argument, NULL, 0, eArgTypeBoolean,
+ { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, 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 }
@@ -989,15 +1012,15 @@ private:
OptionDefinition
CommandObjectBreakpointModify::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "ignore-count", 'i', required_argument, NULL, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
-{ LLDB_OPT_SET_ALL, false, "one-shot", 'o', required_argument, NULL, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
-{ LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument."},
-{ LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."},
-{ LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."},
-{ LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, 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', required_argument, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
-{ LLDB_OPT_SET_1, false, "enable", 'e', no_argument, NULL, 0, eArgTypeNone, "Enable the breakpoint."},
-{ LLDB_OPT_SET_2, false, "disable", 'd', no_argument, NULL, 0, eArgTypeNone, "Disable the breakpoint."},
+{ 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 }
};
@@ -1055,7 +1078,7 @@ protected:
{
// No breakpoint selected; enable all currently set breakpoints.
target->EnableAllBreakpoints ();
- result.AppendMessageWithFormat ("All breakpoints enabled. (%lu breakpoints)\n", num_breakpoints);
+ result.AppendMessageWithFormat ("All breakpoints enabled. (%zu breakpoints)\n", num_breakpoints);
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
@@ -1174,7 +1197,7 @@ protected:
{
// No breakpoint selected; disable all currently set breakpoints.
target->DisableAllBreakpoints ();
- result.AppendMessageWithFormat ("All breakpoints disabled. (%lu breakpoints)\n", num_breakpoints);
+ result.AppendMessageWithFormat ("All breakpoints disabled. (%zu breakpoints)\n", num_breakpoints);
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
@@ -1398,18 +1421,18 @@ private:
OptionDefinition
CommandObjectBreakpointList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "internal", 'i', no_argument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
"Show debugger internal breakpoints" },
- { LLDB_OPT_SET_1, false, "brief", 'b', no_argument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, 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', no_argument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
"Give a full description of the breakpoint and its locations."},
- { LLDB_OPT_SET_3, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
"Explain everything we know about the breakpoint (for debugging debugger bugs)." },
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
@@ -1609,10 +1632,10 @@ private:
OptionDefinition
CommandObjectBreakpointClear::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
"Specify the breakpoint by source location in this particular file."},
- { LLDB_OPT_SET_1, true, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum,
+ { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum,
"Specify the breakpoint by source location at this particular line."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
@@ -1676,7 +1699,7 @@ protected:
else
{
target->RemoveAllBreakpoints ();
- result.AppendMessageWithFormat ("All breakpoints removed. (%lu %s)\n", num_breakpoints, num_breakpoints > 1 ? "breakpoints" : "breakpoint");
+ result.AppendMessageWithFormat ("All breakpoints removed. (%zu %s)\n", num_breakpoints, num_breakpoints > 1 ? "breakpoints" : "breakpoint");
}
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp
index c4504a4c6516..e540461dadae 100644
--- a/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -640,16 +640,16 @@ g_script_option_enumeration[4] =
OptionDefinition
CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "one-liner", 'o', required_argument, NULL, 0, eArgTypeOneLiner,
+ { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeBoolean,
+ { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
"Specify whether breakpoint command execution should terminate on error." },
- { LLDB_OPT_SET_ALL, false, "script-type", 's', required_argument, g_script_option_enumeration, 0, eArgTypeNone,
+ { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypePythonFunction,
+ { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, 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 }
diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp
index 4699aa6d9c4a..6824ead0d9e0 100644
--- a/source/Commands/CommandObjectCommands.cpp
+++ b/source/Commands/CommandObjectCommands.cpp
@@ -156,9 +156,9 @@ protected:
}
else
{
- std::pair<bool,uint64_t> start_idx = {m_options.m_start_idx.OptionWasSet(),m_options.m_start_idx.GetCurrentValue()};
- std::pair<bool,uint64_t> stop_idx = {m_options.m_stop_idx.OptionWasSet(),m_options.m_stop_idx.GetCurrentValue()};
- std::pair<bool,uint64_t> count = {m_options.m_count.OptionWasSet(),m_options.m_count.GetCurrentValue()};
+ std::pair<bool,uint64_t> start_idx(m_options.m_start_idx.OptionWasSet(),m_options.m_start_idx.GetCurrentValue());
+ std::pair<bool,uint64_t> stop_idx(m_options.m_stop_idx.OptionWasSet(),m_options.m_stop_idx.GetCurrentValue());
+ std::pair<bool,uint64_t> count(m_options.m_count.OptionWasSet(),m_options.m_count.GetCurrentValue());
const CommandHistory& history(m_interpreter.GetCommandHistory());
@@ -227,10 +227,10 @@ protected:
OptionDefinition
CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger, "How many history commands to print."},
-{ LLDB_OPT_SET_1, false, "start-index", 's', required_argument, 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', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."},
-{ LLDB_OPT_SET_2, false, "clear", 'C', no_argument, NULL, 0, eArgTypeBoolean, "Clears the current command history."},
+{ 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 }
};
@@ -410,9 +410,9 @@ protected:
OptionDefinition
CommandObjectCommandsSource::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
-{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
-{ LLDB_OPT_SET_ALL, false, "silent-run", 's', required_argument, NULL, 0, eArgTypeBoolean, "If true don't echo commands while executing."},
+{ 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 }
};
@@ -1243,8 +1243,8 @@ private:
OptionDefinition
CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "help" , 'h', required_argument, NULL, 0, eArgTypeNone, "The help text to display for this command."},
-{ LLDB_OPT_SET_1, false, "syntax", 's', required_argument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
+{ 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 }
};
@@ -1517,7 +1517,7 @@ protected:
OptionDefinition
CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "allow-reload", 'r', no_argument, 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."},
+ { 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 }
};
@@ -1828,8 +1828,8 @@ static OptionEnumValueElement g_script_synchro_type[] =
OptionDefinition
CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."},
- { LLDB_OPT_SET_1, false, "synchronicity", 's', required_argument, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."},
+ { 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 }
};
diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp
index 0d40fcd7c0b5..fc148b1899f6 100644
--- a/source/Commands/CommandObjectDisassemble.cpp
+++ b/source/Commands/CommandObjectDisassemble.cpp
@@ -231,28 +231,28 @@ CommandObjectDisassemble::CommandOptions::GetDefinitions ()
OptionDefinition
CommandObjectDisassemble::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "bytes" , 'b', no_argument , NULL, 0, eArgTypeNone, "Show opcode bytes when disassembling."},
-{ LLDB_OPT_SET_ALL, false, "context" , 'C', required_argument , NULL, 0, eArgTypeNumLines, "Number of context lines of source to show."},
-{ LLDB_OPT_SET_ALL, false, "mixed" , 'm', no_argument , NULL, 0, eArgTypeNone, "Enable mixed source and assembly display."},
-{ LLDB_OPT_SET_ALL, false, "raw" , 'r', no_argument , NULL, 0, eArgTypeNone, "Print raw disassembly with no symbol information."},
-{ LLDB_OPT_SET_ALL, false, "plugin" , 'P', required_argument , NULL, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."},
-{ LLDB_OPT_SET_ALL, false, "flavor" , 'F', required_argument , NULL, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. "
+{ 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', required_argument , NULL, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."},
+{ LLDB_OPT_SET_ALL, false, "arch" , 'A', OptionParser::eRequiredArgument , NULL, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."},
{ LLDB_OPT_SET_1 |
- LLDB_OPT_SET_2 , true , "start-address", 's', required_argument , NULL, 0, eArgTypeAddressOrExpression,"Address at which to start disassembling."},
-{ LLDB_OPT_SET_1 , false, "end-address" , 'e', required_argument , NULL, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling."},
+ 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 |
LLDB_OPT_SET_3 |
LLDB_OPT_SET_4 |
- LLDB_OPT_SET_5 , false, "count" , 'c', required_argument , NULL, 0, eArgTypeNumLines, "Number of instructions to display."},
-{ LLDB_OPT_SET_3 , false, "name" , 'n', required_argument , NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
+ 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', no_argument , NULL, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."},
-{ LLDB_OPT_SET_5 , false, "pc" , 'p', no_argument , NULL, 0, eArgTypeNone, "Disassemble around the current pc."},
-{ LLDB_OPT_SET_6 , false, "line" , 'l', no_argument , NULL, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there debug line table information, else disasemble around the pc."},
-{ LLDB_OPT_SET_7 , false, "address" , 'a', required_argument , NULL, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."},
+{ 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 }
};
@@ -453,7 +453,9 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
{
ModuleSP module_sp (symbol_containing_address.GetModule());
SymbolContext sc;
- module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, 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);
diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp
index da472d17331b..6d44f71b8d95 100644
--- a/source/Commands/CommandObjectExpression.cpp
+++ b/source/Commands/CommandObjectExpression.cpp
@@ -19,6 +19,7 @@
#include "lldb/Core/Value.h"
#include "lldb/Core/InputReader.h"
#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Expression/ClangExpressionVariable.h"
#include "lldb/Expression/ClangUserExpression.h"
#include "lldb/Expression/ClangFunction.h"
@@ -49,13 +50,22 @@ CommandObjectExpression::CommandOptions::~CommandOptions ()
{
}
+static OptionEnumValueElement g_description_verbosity_type[] =
+{
+ { eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact", "Only show the description string"},
+ { eLanguageRuntimeDescriptionDisplayVerbosityFull, "full", "Show the full output, including persistent variable's name and type"},
+ { 0, NULL, NULL }
+};
+
OptionDefinition
CommandObjectExpression::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', required_argument, 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', required_argument, NULL, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', required_argument, 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, "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."},
};
@@ -127,6 +137,24 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int
error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
break;
}
+
+ case 'v':
+ if (!option_arg)
+ {
+ m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull;
+ break;
+ }
+ m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
+ if (!error.Success())
+ error.SetErrorStringWithFormat ("unrecognized value for description-verbosity '%s'", option_arg);
+ break;
+
+ case 'g':
+ debug = true;
+ unwind_on_error = false;
+ ignore_breakpoints = false;
+ break;
+
default:
error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
break;
@@ -153,6 +181,8 @@ CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpret
show_summary = true;
try_all_threads = true;
timeout = 0;
+ debug = false;
+ m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
}
const OptionDefinition*
@@ -339,7 +369,10 @@ CommandObjectExpression::EvaluateExpression
.SetKeepInMemory(keep_in_memory)
.SetUseDynamic(m_varobj_options.use_dynamic)
.SetRunOthers(m_command_options.try_all_threads)
- .SetTimeoutUsec(m_command_options.timeout);
+ .SetDebug(m_command_options.debug);
+
+ if (m_command_options.timeout > 0)
+ options.SetTimeoutUsec(m_command_options.timeout);
exe_results = target->EvaluateExpression (expr,
exe_ctx.GetFramePtr(),
@@ -357,11 +390,10 @@ CommandObjectExpression::EvaluateExpression
if (format != eFormatDefault)
result_valobj_sp->SetFormat (format);
- ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(true,format));
+ DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format));
- ValueObject::DumpValueObject (*(output_stream),
- result_valobj_sp.get(), // Variable object to dump
- options);
+ result_valobj_sp->Dump(*output_stream,options);
+
if (result)
result->SetStatus (eReturnStatusSuccessFinishResult);
}
diff --git a/source/Commands/CommandObjectExpression.h b/source/Commands/CommandObjectExpression.h
index 3964f2d423eb..e0703a22a4cc 100644
--- a/source/Commands/CommandObjectExpression.h
+++ b/source/Commands/CommandObjectExpression.h
@@ -55,8 +55,10 @@ public:
bool ignore_breakpoints;
bool show_types;
bool show_summary;
+ bool debug;
uint32_t timeout;
bool try_all_threads;
+ LanguageRuntimeDescriptionDisplayVerbosity m_verbosity;
};
CommandObjectExpression (CommandInterpreter &interpreter);
diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp
index aace3a649602..0ef973261508 100644
--- a/source/Commands/CommandObjectFrame.cpp
+++ b/source/Commands/CommandObjectFrame.cpp
@@ -25,6 +25,7 @@
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -244,7 +245,14 @@ protected:
if (command.GetArgumentCount() == 1)
{
const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
- frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
+ bool success = false;
+ frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0, &success);
+ if (!success)
+ {
+ result.AppendErrorWithFormat ("invalid frame index argument '%s'", frame_idx_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
}
else if (command.GetArgumentCount() == 0)
{
@@ -283,7 +291,7 @@ protected:
OptionDefinition
CommandObjectFrameSelect::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "relative", 'r', required_argument, NULL, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."},
+{ 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 }
};
@@ -400,7 +408,7 @@ protected:
else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
summary_format_sp.reset(new StringSummaryFormat(TypeSummaryImpl::Flags(),m_option_variable.summary_string.GetCurrentValue()));
- ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,eFormatDefault,summary_format_sp));
+ DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,eFormatDefault,summary_format_sp));
if (variable_list)
{
@@ -447,9 +455,7 @@ protected:
if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
s.PutCString (": ");
}
- ValueObject::DumpValueObject (result.GetOutputStream(),
- valobj_sp.get(),
- options);
+ valobj_sp->Dump(result.GetOutputStream(),options);
}
}
}
@@ -493,9 +499,7 @@ protected:
Stream &output_stream = result.GetOutputStream();
options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : NULL);
- ValueObject::DumpValueObject (output_stream,
- valobj_sp.get(),
- options);
+ valobj_sp->Dump(output_stream,options);
}
else
{
@@ -571,9 +575,7 @@ protected:
options.SetFormat(format);
options.SetRootValueObjectName(name_cstr);
- ValueObject::DumpValueObject (result.GetOutputStream(),
- valobj_sp.get(),
- options);
+ valobj_sp->Dump(result.GetOutputStream(),options);
}
}
}
diff --git a/source/Commands/CommandObjectHelp.cpp b/source/Commands/CommandObjectHelp.cpp
index d2c97f91260b..bd0c3938c702 100644
--- a/source/Commands/CommandObjectHelp.cpp
+++ b/source/Commands/CommandObjectHelp.cpp
@@ -54,8 +54,8 @@ CommandObjectHelp::~CommandObjectHelp()
OptionDefinition
CommandObjectHelp::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "show-aliases", 'a', no_argument, NULL, 0, eArgTypeNone, "Show aliases in the command list."},
- { LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', no_argument, NULL, 0, eArgTypeNone, "Hide user-defined commands from the list."},
+ { 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 }
};
diff --git a/source/Commands/CommandObjectLog.cpp b/source/Commands/CommandObjectLog.cpp
index 5fb79154c4ef..2d815846a607 100644
--- a/source/Commands/CommandObjectLog.cpp
+++ b/source/Commands/CommandObjectLog.cpp
@@ -215,15 +215,15 @@ protected:
OptionDefinition
CommandObjectLogEnable::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, 0, eArgTypeFilename, "Set the destination file to log to."},
-{ LLDB_OPT_SET_1, false, "threadsafe", 't', no_argument, NULL, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines." },
-{ LLDB_OPT_SET_1, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone, "Enable verbose logging." },
-{ LLDB_OPT_SET_1, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable debug logging." },
-{ LLDB_OPT_SET_1, false, "sequence", 's', no_argument, NULL, 0, eArgTypeNone, "Prepend all log lines with an increasing integer sequence id." },
-{ LLDB_OPT_SET_1, false, "timestamp", 'T', no_argument, NULL, 0, eArgTypeNone, "Prepend all log lines with a timestamp." },
-{ LLDB_OPT_SET_1, false, "pid-tid", 'p', no_argument, 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', no_argument, 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', no_argument, NULL, 0, eArgTypeNone, "Append a stack backtrace to each log line." },
+{ 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 }
};
diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp
index 4725a4da6578..2ee275e11f66 100644
--- a/source/Commands/CommandObjectMemory.cpp
+++ b/source/Commands/CommandObjectMemory.cpp
@@ -12,6 +12,8 @@
#include "CommandObjectMemory.h"
// C Includes
+#include <inttypes.h>
+
// C++ Includes
// Other libraries and framework includes
// Project includes
@@ -21,6 +23,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -39,12 +42,12 @@ using namespace lldb_private;
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
- { LLDB_OPT_SET_2, false, "binary" ,'b', no_argument , 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', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
+ { 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|
LLDB_OPT_SET_2|
- LLDB_OPT_SET_3, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
+ LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
};
@@ -648,7 +651,7 @@ protected:
}
else if (m_format_options.GetCountValue().OptionWasSet())
{
- result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %lu), not both.\n", end_addr, item_count);
+ result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %zu), not both.\n", end_addr, item_count);
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -705,7 +708,7 @@ protected:
}
if (bytes_read < total_byte_size)
- result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr);
+ result.AppendWarningWithFormat("Not all bytes (%zu/%zu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr);
}
else
{
@@ -834,11 +837,9 @@ protected:
if (format != eFormatDefault)
valobj_sp->SetFormat (format);
- ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,format));
+ DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
- ValueObject::DumpValueObject (*output_stream,
- valobj_sp.get(),
- options);
+ valobj_sp->Dump(*output_stream,options);
}
else
{
@@ -859,16 +860,28 @@ protected:
Format format = m_format_options.GetFormat();
if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
- && (item_byte_size != 1)
- && (item_count == 1))
+ && (item_byte_size != 1))
{
- // this turns requests such as
- // memory read -fc -s10 -c1 *charPtrPtr
- // which make no sense (what is a char of size 10?)
- // into a request for fetching 10 chars of size 1 from the same memory location
- format = eFormatCharArray;
- item_count = item_byte_size;
- item_byte_size = 1;
+ // if a count was not passed, or it is 1
+ if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
+ {
+ // this turns requests such as
+ // memory read -fc -s10 -c1 *charPtrPtr
+ // which make no sense (what is a char of size 10?)
+ // into a request for fetching 10 chars of size 1 from the same memory location
+ format = eFormatCharArray;
+ item_count = item_byte_size;
+ item_byte_size = 1;
+ }
+ else
+ {
+ // 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.SetStatus(eReturnStatusFailed);
+ return false;
+ }
}
assert (output_stream);
@@ -905,8 +918,8 @@ protected:
OptionDefinition
g_memory_write_option_table[] =
{
-{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
-{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
+{ 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."},
};
@@ -1219,7 +1232,7 @@ protected:
}
else if (!UIntValueIsValidForSize (uval64, item_byte_size))
{
- result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", 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.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1247,7 +1260,7 @@ protected:
}
else if (!UIntValueIsValidForSize (uval64, item_byte_size))
{
- result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", 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.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1287,7 +1300,7 @@ protected:
}
else if (!SIntValueIsValidForSize (sval64, item_byte_size))
{
- result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %lu byte signed integer value.\n", 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.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1304,7 +1317,7 @@ protected:
}
else if (!UIntValueIsValidForSize (uval64, item_byte_size))
{
- result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %lu byte unsigned integer value.\n", 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.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1321,7 +1334,7 @@ protected:
}
else if (!UIntValueIsValidForSize (uval64, item_byte_size))
{
- result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %lu byte unsigned integer value.\n", 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.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp
index c2185e598ad4..ace1ef5b53fb 100644
--- a/source/Commands/CommandObjectPlatform.cpp
+++ b/source/Commands/CommandObjectPlatform.cpp
@@ -26,10 +26,158 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/Utils.h"
using namespace lldb;
using namespace lldb_private;
+static mode_t
+ParsePermissionString(const char* permissions)
+{
+ if (strlen(permissions) != 9)
+ return (mode_t)(-1);
+ bool user_r,user_w,user_x,
+ group_r,group_w,group_x,
+ world_r,world_w,world_x;
+
+ user_r = (permissions[0] == 'r');
+ user_w = (permissions[1] == 'w');
+ user_x = (permissions[2] == 'x');
+
+ group_r = (permissions[3] == 'r');
+ group_w = (permissions[4] == 'w');
+ group_x = (permissions[5] == 'x');
+
+ world_r = (permissions[6] == 'r');
+ world_w = (permissions[7] == 'w');
+ world_x = (permissions[8] == 'x');
+
+ mode_t user,group,world;
+ user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
+ group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
+ world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
+
+ return user | group | world;
+}
+
+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." },
+
+};
+
+class OptionPermissions : public lldb_private::OptionGroup
+{
+public:
+ OptionPermissions ()
+ {
+ }
+
+ virtual
+ ~OptionPermissions ()
+ {
+ }
+
+ virtual lldb_private::Error
+ SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+ {
+ Error error;
+ char short_option = (char) GetDefinitions()[option_idx].short_option;
+ switch (short_option)
+ {
+ case 'v':
+ {
+ bool ok;
+ uint32_t perms = Args::StringToUInt32(option_arg, 777, 8, &ok);
+ if (!ok)
+ error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg);
+ else
+ m_permissions = perms;
+ }
+ break;
+ case 's':
+ {
+ mode_t perms = ParsePermissionString(option_arg);
+ if (perms == (mode_t)-1)
+ error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg);
+ else
+ m_permissions = perms;
+ }
+ case 'r':
+ m_permissions |= File::ePermissionsUserRead;
+ break;
+ case 'w':
+ m_permissions |= File::ePermissionsUserWrite;
+ break;
+ case 'x':
+ m_permissions |= File::ePermissionsUserExecute;
+ break;
+ case 'R':
+ m_permissions |= File::ePermissionsGroupRead;
+ break;
+ case 'W':
+ m_permissions |= File::ePermissionsGroupWrite;
+ break;
+ case 'X':
+ m_permissions |= File::ePermissionsGroupExecute;
+ break;
+ case 'd':
+ m_permissions |= File::ePermissionsWorldRead;
+ break;
+ case 't':
+ m_permissions |= File::ePermissionsWorldWrite;
+ break;
+ case 'e':
+ m_permissions |= File::ePermissionsWorldExecute;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ OptionParsingStarting (CommandInterpreter &interpreter)
+ {
+ m_permissions = 0;
+ }
+
+ virtual uint32_t
+ GetNumDefinitions ()
+ {
+ return llvm::array_lengthof(g_permissions_options);
+ }
+
+ const lldb_private::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_permissions_options;
+ }
+
+ // Instance variables to hold the values for command options.
+
+ uint32_t m_permissions;
+private:
+ DISALLOW_COPY_AND_ASSIGN(OptionPermissions);
+};
//----------------------------------------------------------------------
// "platform select <platform-name>"
@@ -274,11 +422,26 @@ protected:
}
else
{
- result.AppendError ("no platform us currently selected\n");
+ result.AppendError ("no platform is currently selected\n");
result.SetStatus (eReturnStatusFailed);
}
return result.Succeeded();
}
+
+ virtual Options *
+ GetOptions ()
+ {
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ OptionGroupOptions* m_platform_options = NULL;
+ if (platform_sp)
+ {
+ m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
+ if (m_platform_options != NULL && !m_platform_options->m_did_finalize)
+ m_platform_options->Finalize();
+ }
+ return m_platform_options;
+ }
+
};
//----------------------------------------------------------------------
@@ -359,6 +522,680 @@ protected:
return result.Succeeded();
}
};
+
+//----------------------------------------------------------------------
+// "platform mkdir"
+//----------------------------------------------------------------------
+class CommandObjectPlatformMkDir : public CommandObjectParsed
+{
+public:
+ CommandObjectPlatformMkDir (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "platform mkdir",
+ "Make a new directory on the remote end.",
+ NULL,
+ 0),
+ m_options(interpreter)
+ {
+ }
+
+ virtual
+ ~CommandObjectPlatformMkDir ()
+ {
+ }
+
+ virtual bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (platform_sp)
+ {
+ std::string cmd_line;
+ args.GetCommandString(cmd_line);
+ mode_t perms;
+ const OptionPermissions* options_permissions = (OptionPermissions*)m_options.GetGroupWithOption('r');
+ if (options_permissions)
+ perms = options_permissions->m_permissions;
+ else
+ perms = 0000700 | 0000070 | 0000007;
+ uint32_t retcode = platform_sp->MakeDirectory(cmd_line,perms);
+ result.AppendMessageWithFormat("Status = %d\n",retcode);
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendError ("no platform currently selected\n");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+
+ virtual Options *
+ GetOptions ()
+ {
+ if (m_options.DidFinalize() == false)
+ {
+ m_options.Append(new OptionPermissions());
+ m_options.Finalize();
+ }
+ return &m_options;
+ }
+ OptionGroupOptions m_options;
+
+};
+
+//----------------------------------------------------------------------
+// "platform fopen"
+//----------------------------------------------------------------------
+class CommandObjectPlatformFOpen : public CommandObjectParsed
+{
+public:
+ CommandObjectPlatformFOpen (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "platform file open",
+ "Open a file on the remote end.",
+ NULL,
+ 0),
+ m_options(interpreter)
+ {
+ }
+
+ virtual
+ ~CommandObjectPlatformFOpen ()
+ {
+ }
+
+ virtual bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (platform_sp)
+ {
+ Error error;
+ std::string cmd_line;
+ args.GetCommandString(cmd_line);
+ mode_t perms;
+ const OptionPermissions* options_permissions = (OptionPermissions*)m_options.GetGroupWithOption('r');
+ if (options_permissions)
+ perms = options_permissions->m_permissions;
+ else
+ perms = 0000700 | 0000070 | 0000007;
+ lldb::user_id_t fd = platform_sp->OpenFile(FileSpec(cmd_line.c_str(),false),
+ File::eOpenOptionRead | File::eOpenOptionWrite |
+ File::eOpenOptionAppend | File::eOpenOptionCanCreate,
+ perms,
+ error);
+ if (error.Success())
+ {
+ result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n",fd);
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendError(error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("no platform currently selected\n");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+ virtual Options *
+ GetOptions ()
+ {
+ if (m_options.DidFinalize() == false)
+ {
+ m_options.Append(new OptionPermissions());
+ m_options.Finalize();
+ }
+ return &m_options;
+ }
+ OptionGroupOptions m_options;
+};
+
+//----------------------------------------------------------------------
+// "platform fclose"
+//----------------------------------------------------------------------
+class CommandObjectPlatformFClose : public CommandObjectParsed
+{
+public:
+ CommandObjectPlatformFClose (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "platform file close",
+ "Close a file on the remote end.",
+ NULL,
+ 0)
+ {
+ }
+
+ virtual
+ ~CommandObjectPlatformFClose ()
+ {
+ }
+
+ virtual bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (platform_sp)
+ {
+ std::string cmd_line;
+ args.GetCommandString(cmd_line);
+ const lldb::user_id_t fd = Args::StringToUInt64(cmd_line.c_str(), UINT64_MAX);
+ Error error;
+ bool success = platform_sp->CloseFile(fd, error);
+ if (success)
+ {
+ result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendError(error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("no platform currently selected\n");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+//----------------------------------------------------------------------
+// "platform fread"
+//----------------------------------------------------------------------
+class CommandObjectPlatformFRead : public CommandObjectParsed
+{
+public:
+ CommandObjectPlatformFRead (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "platform file read",
+ "Read data from a file on the remote end.",
+ NULL,
+ 0),
+ m_options (interpreter)
+ {
+ }
+
+ virtual
+ ~CommandObjectPlatformFRead ()
+ {
+ }
+
+ virtual bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (platform_sp)
+ {
+ std::string cmd_line;
+ args.GetCommandString(cmd_line);
+ const lldb::user_id_t fd = Args::StringToUInt64(cmd_line.c_str(), UINT64_MAX);
+ std::string buffer(m_options.m_count,0);
+ Error error;
+ uint32_t retcode = platform_sp->ReadFile(fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
+ result.AppendMessageWithFormat("Return = %d\n",retcode);
+ result.AppendMessageWithFormat("Data = \"%s\"\n",buffer.c_str());
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendError ("no platform currently selected\n");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+protected:
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options (interpreter)
+ {
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg)
+ {
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+ bool success = false;
+
+ switch (short_option)
+ {
+ case 'o':
+ m_offset = Args::StringToUInt32(option_arg, 0, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
+ break;
+ case 'c':
+ m_count = Args::StringToUInt32(option_arg, 0, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_offset = 0;
+ m_count = 1;
+ }
+
+ 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.
+
+ uint32_t m_offset;
+ uint32_t m_count;
+ };
+ CommandOptions m_options;
+};
+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 }
+};
+
+
+//----------------------------------------------------------------------
+// "platform fwrite"
+//----------------------------------------------------------------------
+class CommandObjectPlatformFWrite : public CommandObjectParsed
+{
+public:
+ CommandObjectPlatformFWrite (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "platform file write",
+ "Write data to a file on the remote end.",
+ NULL,
+ 0),
+ m_options (interpreter)
+ {
+ }
+
+ virtual
+ ~CommandObjectPlatformFWrite ()
+ {
+ }
+
+ virtual bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (platform_sp)
+ {
+ std::string cmd_line;
+ args.GetCommandString(cmd_line);
+ Error error;
+ const lldb::user_id_t fd = Args::StringToUInt64(cmd_line.c_str(), UINT64_MAX);
+ uint32_t retcode = platform_sp->WriteFile (fd,
+ m_options.m_offset,
+ &m_options.m_data[0],
+ m_options.m_data.size(),
+ error);
+ result.AppendMessageWithFormat("Return = %d\n",retcode);
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendError ("no platform currently selected\n");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+protected:
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options (interpreter)
+ {
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg)
+ {
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+ bool success = false;
+
+ switch (short_option)
+ {
+ case 'o':
+ m_offset = Args::StringToUInt32(option_arg, 0, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
+ break;
+ case 'd':
+ m_data.assign(option_arg);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_offset = 0;
+ m_data.clear();
+ }
+
+ 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.
+
+ uint32_t m_offset;
+ std::string m_data;
+ };
+ CommandOptions m_options;
+};
+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 }
+};
+
+class CommandObjectPlatformFile : public CommandObjectMultiword
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CommandObjectPlatformFile (CommandInterpreter &interpreter) :
+ CommandObjectMultiword (interpreter,
+ "platform file",
+ "A set of commands to manage file access through a platform",
+ "platform file [open|close|read|write] ...")
+ {
+ LoadSubCommand ("open", CommandObjectSP (new CommandObjectPlatformFOpen (interpreter)));
+ LoadSubCommand ("close", CommandObjectSP (new CommandObjectPlatformFClose (interpreter)));
+ LoadSubCommand ("read", CommandObjectSP (new CommandObjectPlatformFRead (interpreter)));
+ LoadSubCommand ("write", CommandObjectSP (new CommandObjectPlatformFWrite (interpreter)));
+ }
+
+ virtual
+ ~CommandObjectPlatformFile ()
+ {
+ }
+
+private:
+ //------------------------------------------------------------------
+ // For CommandObjectPlatform only
+ //------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformFile);
+};
+
+//----------------------------------------------------------------------
+// "platform get-file remote-file-path host-file-path"
+//----------------------------------------------------------------------
+class CommandObjectPlatformGetFile : public CommandObjectParsed
+{
+public:
+ CommandObjectPlatformGetFile (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "platform get-file",
+ "Transfer a file from the remote end to the local host.",
+ "platform get-file <remote-file-spec> <local-file-spec>",
+ 0)
+ {
+ SetHelpLong(
+"Examples: \n\
+\n\
+ platform get-file /the/remote/file/path /the/local/file/path\n\
+ # Transfer a file from the remote end with file path /the/remote/file/path to the local host.\n");
+
+ CommandArgumentEntry arg1, arg2;
+ CommandArgumentData file_arg_remote, file_arg_host;
+
+ // Define the first (and only) variant of this arg.
+ file_arg_remote.arg_type = eArgTypeFilename;
+ file_arg_remote.arg_repetition = eArgRepeatPlain;
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg1.push_back (file_arg_remote);
+
+ // Define the second (and only) variant of this arg.
+ file_arg_host.arg_type = eArgTypeFilename;
+ file_arg_host.arg_repetition = eArgRepeatPlain;
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg2.push_back (file_arg_host);
+
+ // Push the data for the first and the second arguments into the m_arguments vector.
+ m_arguments.push_back (arg1);
+ m_arguments.push_back (arg2);
+ }
+
+ virtual
+ ~CommandObjectPlatformGetFile ()
+ {
+ }
+
+ virtual bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ // If the number of arguments is incorrect, issue an error message.
+ if (args.GetArgumentCount() != 2)
+ {
+ result.GetErrorStream().Printf("error: required arguments missing; specify both the source and destination file paths\n");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (platform_sp)
+ {
+ const char *remote_file_path = args.GetArgumentAtIndex(0);
+ const char *local_file_path = args.GetArgumentAtIndex(1);
+ Error error = platform_sp->GetFile(FileSpec(remote_file_path, false),
+ FileSpec(local_file_path, false));
+ if (error.Success())
+ {
+ result.AppendMessageWithFormat("successfully get-file from %s (remote) to %s (host)\n",
+ remote_file_path, local_file_path);
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendMessageWithFormat("get-file failed: %s\n", error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("no platform currently selected\n");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+//----------------------------------------------------------------------
+// "platform get-size remote-file-path"
+//----------------------------------------------------------------------
+class CommandObjectPlatformGetSize : public CommandObjectParsed
+{
+public:
+ CommandObjectPlatformGetSize (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "platform get-size",
+ "Get the file size from the remote end.",
+ "platform get-size <remote-file-spec>",
+ 0)
+ {
+ SetHelpLong(
+"Examples: \n\
+\n\
+ platform get-size /the/remote/file/path\n\
+ # Get the file size from the remote end with path /the/remote/file/path.\n");
+
+ CommandArgumentEntry arg1;
+ CommandArgumentData file_arg_remote;
+
+ // Define the first (and only) variant of this arg.
+ file_arg_remote.arg_type = eArgTypeFilename;
+ file_arg_remote.arg_repetition = eArgRepeatPlain;
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg1.push_back (file_arg_remote);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg1);
+ }
+
+ virtual
+ ~CommandObjectPlatformGetSize ()
+ {
+ }
+
+ virtual bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ // If the number of arguments is incorrect, issue an error message.
+ if (args.GetArgumentCount() != 1)
+ {
+ result.GetErrorStream().Printf("error: required argument missing; specify the source file path as the only argument\n");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (platform_sp)
+ {
+ std::string remote_file_path(args.GetArgumentAtIndex(0));
+ user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path.c_str(), false));
+ if (size != UINT64_MAX)
+ {
+ result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64 "\n", remote_file_path.c_str(), size);
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendMessageWithFormat("Eroor getting file size of %s (remote)\n", remote_file_path.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("no platform currently selected\n");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+//----------------------------------------------------------------------
+// "platform put-file"
+//----------------------------------------------------------------------
+class CommandObjectPlatformPutFile : public CommandObjectParsed
+{
+public:
+ CommandObjectPlatformPutFile (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "platform put-file",
+ "Transfer a file from this system to the remote end.",
+ NULL,
+ 0)
+ {
+ }
+
+ virtual
+ ~CommandObjectPlatformPutFile ()
+ {
+ }
+
+ virtual bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ const char* src = args.GetArgumentAtIndex(0);
+ const char* dst = args.GetArgumentAtIndex(1);
+
+ FileSpec src_fs(src, true);
+ FileSpec dst_fs(dst, false);
+
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (platform_sp)
+ {
+ Error error (platform_sp->PutFile(src_fs, dst_fs));
+ if (error.Success())
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendError (error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("no platform currently selected\n");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
//----------------------------------------------------------------------
// "platform process launch"
//----------------------------------------------------------------------
@@ -744,20 +1581,20 @@ protected:
OptionDefinition
CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1 , false, "pid" , 'p', required_argument, NULL, 0, eArgTypePid , "List the process info for a specific process ID." },
-{ LLDB_OPT_SET_2 , true , "name" , 'n', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." },
-{ LLDB_OPT_SET_3 , true , "ends-with" , 'e', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that end with a string." },
-{ LLDB_OPT_SET_4 , true , "starts-with", 's', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that start with a string." },
-{ LLDB_OPT_SET_5 , true , "contains" , 'c', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that contain a string." },
-{ LLDB_OPT_SET_6 , true , "regex" , 'r', required_argument, NULL, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "parent" , 'P', required_argument, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "uid" , 'u', required_argument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching user ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "euid" , 'U', required_argument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching effective user ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "gid" , 'g', required_argument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching group ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "egid" , 'G', required_argument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching effective group ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." },
-{ LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args" , 'A', no_argument , NULL, 0, eArgTypeNone , "Show process arguments instead of the process executable basename." },
-{ LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose" , 'v', no_argument , NULL, 0, eArgTypeNone , "Enable verbose output." },
+{ 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 }
};
@@ -868,8 +1705,206 @@ protected:
}
};
+class CommandObjectPlatformProcessAttach : public CommandObjectParsed
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options(interpreter)
+ {
+ // Keep default values of all options in one place: OptionParsingStarting ()
+ OptionParsingStarting ();
+ }
+
+ ~CommandOptions ()
+ {
+ }
+
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg)
+ {
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+ bool success = false;
+ switch (short_option)
+ {
+ case 'p':
+ {
+ lldb::pid_t pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
+ if (!success || pid == LLDB_INVALID_PROCESS_ID)
+ {
+ error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
+ }
+ else
+ {
+ attach_info.SetProcessID (pid);
+ }
+ }
+ break;
+
+ case 'P':
+ attach_info.SetProcessPluginName (option_arg);
+ break;
+
+ case 'n':
+ attach_info.GetExecutableFile().SetFile(option_arg, false);
+ break;
+
+ case 'w':
+ attach_info.SetWaitForLaunch(true);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
+ break;
+ }
+ return error;
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ attach_info.Clear();
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ virtual bool
+ HandleOptionArgumentCompletion (Args &input,
+ int cursor_index,
+ int char_pos,
+ OptionElementVector &opt_element_vector,
+ int opt_element_index,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+ {
+ int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
+ int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
+
+ // We are only completing the name option for now...
+
+ const OptionDefinition *opt_defs = GetDefinitions();
+ if (opt_defs[opt_defs_index].short_option == 'n')
+ {
+ // Are we in the name?
+
+ // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
+ // use the default plugin.
+
+ const char *partial_name = NULL;
+ partial_name = input.GetArgumentAtIndex(opt_arg_pos);
+
+ PlatformSP platform_sp (m_interpreter.GetPlatform (true));
+ if (platform_sp)
+ {
+ ProcessInstanceInfoList process_infos;
+ ProcessInstanceInfoMatch match_info;
+ if (partial_name)
+ {
+ match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false);
+ match_info.SetNameMatchType(eNameMatchStartsWith);
+ }
+ platform_sp->FindProcesses (match_info, process_infos);
+ const uint32_t num_matches = process_infos.GetSize();
+ if (num_matches > 0)
+ {
+ for (uint32_t i=0; i<num_matches; ++i)
+ {
+ matches.AppendString (process_infos.GetProcessNameAtIndex(i),
+ process_infos.GetProcessNameLengthAtIndex(i));
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ ProcessAttachInfo attach_info;
+ };
+
+ CommandObjectPlatformProcessAttach (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "platform process attach",
+ "Attach to a process.",
+ "platform process attach <cmd-options>"),
+ m_options (interpreter)
+ {
+ }
+
+ ~CommandObjectPlatformProcessAttach ()
+ {
+ }
+
+ bool
+ DoExecute (Args& command,
+ CommandReturnObject &result)
+ {
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (platform_sp)
+ {
+ Error err;
+ ProcessSP remote_process_sp =
+ platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, m_interpreter.GetDebugger().GetListener(), err);
+ if (err.Fail())
+ {
+ result.AppendError(err.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else if (remote_process_sp.get() == NULL)
+ {
+ result.AppendError("could not attach: unknown reason");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendError ("no platform is currently selected");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+protected:
+
+ CommandOptions m_options;
+};
+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 }
+};
+
class CommandObjectPlatformProcess : public CommandObjectMultiword
{
@@ -883,7 +1918,7 @@ public:
"A set of commands to query, launch and attach to platform processes",
"platform process [attach|launch|list] ...")
{
-// LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter)));
+ LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter)));
LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter)));
LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter)));
LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter)));
@@ -902,16 +1937,84 @@ private:
DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess);
};
-
+//----------------------------------------------------------------------
+// "platform shell"
+//----------------------------------------------------------------------
class CommandObjectPlatformShell : public CommandObjectRaw
{
public:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options(interpreter),
+ timeout(10)
+ {
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual uint32_t
+ GetNumDefinitions ()
+ {
+ return 1;
+ }
+
+ virtual const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ virtual Error
+ SetOptionValue (uint32_t option_idx,
+ const char *option_value)
+ {
+ Error error;
+
+ const char short_option = (char) g_option_table[option_idx].short_option;
+
+ switch (short_option)
+ {
+ case 't':
+ {
+ bool success;
+ timeout = Args::StringToUInt32(option_value, 10, 10, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("could not convert \"%s\" to a numeric value.", option_value);
+ break;
+ }
+ default:
+ error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ virtual void
+ OptionParsingStarting ()
+ {
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+ uint32_t timeout;
+ };
+
CommandObjectPlatformShell (CommandInterpreter &interpreter) :
- CommandObjectRaw (interpreter,
- "platform shell",
- "Run a shell command on a the selected platform.",
- "platform shell <shell-command>",
- 0)
+ CommandObjectRaw (interpreter,
+ "platform shell",
+ "Run a shell command on a the selected platform.",
+ "platform shell <shell-command>",
+ 0),
+ m_options(interpreter)
{
}
@@ -920,31 +2023,89 @@ public:
{
}
-protected:
+ virtual
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
virtual bool
DoExecute (const char *raw_command_line, CommandReturnObject &result)
{
- // TODO: Implement "Platform::RunShellCommand()" and switch over to using
- // the current platform when it is in the interface.
- const char *working_dir = NULL;
- std::string output;
- int status = -1;
- int signo = -1;
- Error error (Host::RunShellCommand (raw_command_line, working_dir, &status, &signo, &output, 10));
- if (!output.empty())
- result.GetOutputStream().PutCString(output.c_str());
- if (status > 0)
- {
- if (signo > 0)
- {
- const char *signo_cstr = Host::GetSignalAsCString(signo);
- if (signo_cstr)
- result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr);
+ m_options.NotifyOptionParsingStarting();
+
+ const char* expr = NULL;
+
+ // Print out an usage syntax on an empty command line.
+ if (raw_command_line[0] == '\0')
+ {
+ result.GetOutputStream().Printf("%s\n", this->GetSyntax());
+ return true;
+ }
+
+ if (raw_command_line[0] == '-')
+ {
+ // We have some options and these options MUST end with --.
+ const char *end_options = NULL;
+ const char *s = raw_command_line;
+ while (s && s[0])
+ {
+ end_options = ::strstr (s, "--");
+ if (end_options)
+ {
+ end_options += 2; // Get past the "--"
+ if (::isspace (end_options[0]))
+ {
+ expr = end_options;
+ while (::isspace (*expr))
+ ++expr;
+ break;
+ }
+ }
+ s = end_options;
+ }
+
+ if (end_options)
+ {
+ Args args (raw_command_line, end_options - raw_command_line);
+ if (!ParseOptions (args, result))
+ return false;
+ }
+ }
+
+ if (expr == NULL)
+ expr = raw_command_line;
+
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ Error error;
+ if (platform_sp)
+ {
+ const char *working_dir = NULL;
+ std::string output;
+ int status = -1;
+ int signo = -1;
+ error = (platform_sp->RunShellCommand (expr, working_dir, &status, &signo, &output, m_options.timeout));
+ if (!output.empty())
+ result.GetOutputStream().PutCString(output.c_str());
+ if (status > 0)
+ {
+ if (signo > 0)
+ {
+ const char *signo_cstr = Host::GetSignalAsCString(signo);
+ if (signo_cstr)
+ result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr);
+ else
+ result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo);
+ }
else
- result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo);
+ result.GetOutputStream().Printf("error: command returned with status %i\n", status);
}
- else
- result.GetOutputStream().Printf("error: command returned with status %i\n", status);
+ }
+ else
+ {
+ result.GetOutputStream().Printf("error: cannot run remote shell commands without a platform\n");
+ error.SetErrorString("error: cannot run remote shell commands without a platform");
}
if (error.Fail())
@@ -958,6 +2119,208 @@ protected:
}
return true;
}
+ CommandOptions m_options;
+};
+
+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 }
+};
+
+struct RecurseCopyBaton
+{
+ const std::string& destination;
+ const PlatformSP& platform_sp;
+ Error error;
+};
+
+
+static FileSpec::EnumerateDirectoryResult
+RecurseCopy_Callback (void *baton,
+ FileSpec::FileType file_type,
+ const FileSpec &spec)
+{
+ RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton;
+ switch (file_type)
+ {
+ case FileSpec::eFileTypePipe:
+ case FileSpec::eFileTypeSocket:
+ // we have no way to copy pipes and sockets - ignore them and continue
+ return FileSpec::eEnumerateDirectoryResultNext;
+ break;
+
+ case FileSpec::eFileTypeSymbolicLink:
+ // what to do for symlinks?
+ return FileSpec::eEnumerateDirectoryResultNext;
+ break;
+
+ case FileSpec::eFileTypeDirectory:
+ {
+ // make the new directory and get in there
+ FileSpec new_directory(rc_baton->destination.c_str(),false);
+ new_directory.AppendPathComponent(spec.GetLastPathComponent());
+ uint32_t errcode = rc_baton->platform_sp->MakeDirectory(new_directory, 0777);
+ std::string new_directory_path (new_directory.GetPath());
+ if (errcode != 0)
+ {
+ rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end",new_directory_path.c_str());
+ return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ }
+
+ // now recurse
+ std::string local_path (spec.GetPath());
+ RecurseCopyBaton rc_baton2 = { new_directory_path, rc_baton->platform_sp, Error() };
+ FileSpec::EnumerateDirectory(local_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2);
+ if (rc_baton2.error.Fail())
+ {
+ rc_baton->error.SetErrorString(rc_baton2.error.AsCString());
+ return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ }
+ return FileSpec::eEnumerateDirectoryResultNext;
+ }
+ break;
+
+ case FileSpec::eFileTypeRegular:
+ {
+ // copy the file and keep going
+ std::string dest(rc_baton->destination);
+ dest.append(spec.GetFilename().GetCString());
+ Error err = rc_baton->platform_sp->PutFile(spec, FileSpec(dest.c_str(), false));
+ if (err.Fail())
+ {
+ rc_baton->error.SetErrorString(err.AsCString());
+ return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ }
+ return FileSpec::eEnumerateDirectoryResultNext;
+ }
+ break;
+
+ case FileSpec::eFileTypeInvalid:
+ case FileSpec::eFileTypeOther:
+ case FileSpec::eFileTypeUnknown:
+ rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s/%s", spec.GetDirectory().GetCString(), spec.GetFilename().GetCString());
+ return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ break;
+ }
+}
+
+//----------------------------------------------------------------------
+// "platform install" - install a target to a remote end
+//----------------------------------------------------------------------
+class CommandObjectPlatformInstall : public CommandObjectParsed
+{
+public:
+ CommandObjectPlatformInstall (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "platform target-install",
+ "Install a target (bundle or executable file) to the remote end.",
+ "platform target-install <local-thing> <remote-sandbox>",
+ 0)
+ {
+ }
+
+ virtual
+ ~CommandObjectPlatformInstall ()
+ {
+ }
+
+ virtual bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ if (args.GetArgumentCount() != 2)
+ {
+ result.AppendError("platform target-install takes two arguments");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ // TODO: move the bulk of this code over to the platform itself
+ std::string local_thing(args.GetArgumentAtIndex(0));
+ std::string remote_sandbox(args.GetArgumentAtIndex(1));
+ FileSpec source(local_thing.c_str(), true);
+ if (source.Exists() == false)
+ {
+ result.AppendError("source location does not exist or is not accessible");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (!platform_sp)
+ {
+ result.AppendError ("no platform currently selected");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ FileSpec::FileType source_type(source.GetFileType());
+ if (source_type == FileSpec::eFileTypeDirectory)
+ {
+ if (platform_sp->GetSupportsRSync())
+ {
+ FileSpec remote_folder(remote_sandbox.c_str(), false);
+ Error rsync_err = platform_sp->PutFile(source, remote_folder);
+ if (rsync_err.Success())
+ {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return result.Succeeded();
+ }
+ }
+ FileSpec remote_folder(remote_sandbox.c_str(), false);
+ remote_folder.AppendPathComponent(source.GetLastPathComponent());
+ // TODO: default permissions are bad
+ uint32_t errcode = platform_sp->MakeDirectory(remote_folder, 0777);
+ if (errcode != 0)
+ {
+ result.AppendError("unable to setup target directory on remote end");
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return result.Succeeded();
+ }
+ // now recurse
+ std::string remote_folder_path (remote_folder.GetPath());
+ Error err = RecurseCopy(source,remote_folder_path,platform_sp);
+ if (err.Fail())
+ {
+ result.AppendError(err.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ }
+ else
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return result.Succeeded();
+ }
+ else if (source_type == FileSpec::eFileTypeRegular)
+ {
+ // just a plain file - push it to remote and be done
+ remote_sandbox.append(source.GetFilename().GetCString());
+ FileSpec destination(remote_sandbox.c_str(),false);
+ Error err = platform_sp->PutFile(source, destination);
+ if (err.Success())
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ {
+ result.AppendError(err.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+ else
+ {
+ result.AppendError("source is not a known type of file");
+ result.SetStatus(eReturnStatusFailed);
+ return result.Succeeded();
+ }
+ }
+private:
+
+ Error
+ RecurseCopy (const FileSpec& source,
+ const std::string& destination,
+ const PlatformSP& platform_sp)
+ {
+ std::string source_path (source.GetPath());
+ RecurseCopyBaton baton = { destination, platform_sp, Error() };
+ FileSpec::EnumerateDirectory(source_path.c_str(), true, true, true, RecurseCopy_Callback, &baton);
+ return baton.error;
+ }
};
//----------------------------------------------------------------------
@@ -974,8 +2337,16 @@ CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) :
LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
+#ifdef LLDB_CONFIGURATION_DEBUG
+ LoadSubCommand ("mkdir", CommandObjectSP (new CommandObjectPlatformMkDir (interpreter)));
+ LoadSubCommand ("file", CommandObjectSP (new CommandObjectPlatformFile (interpreter)));
+ LoadSubCommand ("get-file", CommandObjectSP (new CommandObjectPlatformGetFile (interpreter)));
+ LoadSubCommand ("get-size", CommandObjectSP (new CommandObjectPlatformGetSize (interpreter)));
+ LoadSubCommand ("put-file", CommandObjectSP (new CommandObjectPlatformPutFile (interpreter)));
+#endif
LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter)));
LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter)));
+ LoadSubCommand ("target-install", CommandObjectSP (new CommandObjectPlatformInstall (interpreter)));
}
diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp
index 4c406a4f2aae..8bdec6e4573a 100644
--- a/source/Commands/CommandObjectProcess.cpp
+++ b/source/Commands/CommandObjectProcess.cpp
@@ -302,7 +302,7 @@ protected:
if (m_options.launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false)
{
result.SetStatus (eReturnStatusSuccessContinuingNoResult);
- StateType state = process->WaitForProcessToStop (NULL);
+ StateType state = process->WaitForProcessToStop (NULL, NULL, false);
if (state == eStateStopped)
{
@@ -359,14 +359,14 @@ protected:
//OptionDefinition
//CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
//{
-//{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
-//{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypeDirectoryName, "Redirect stdin for the process to <path>."},
-//{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypeDirectoryName, "Redirect stdout for the process to <path>."},
-//{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypeDirectoryName, "Redirect stderr for the process to <path>."},
-//{ SET1 | SET2 | SET3, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
-//{ SET2 , false, "tty", 't', optional_argument, NULL, 0, eArgTypeDirectoryName, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."},
-//{ SET3, false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
-//{ SET1 | SET2 | SET3, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."},
+//{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
+//{ SET1 , false, "stdin", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Redirect stdin for the process to <path>."},
+//{ SET1 , false, "stdout", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Redirect stdout for the process to <path>."},
+//{ SET1 , false, "stderr", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Redirect stderr for the process to <path>."},
+//{ SET1 | SET2 | SET3, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
+//{ SET2 , false, "tty", 't', OptionParser::eOptionalArgument, NULL, 0, eArgTypeDirectoryName, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."},
+//{ SET3, false, "no-stdio", 'n', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
+//{ SET1 | SET2 | SET3, false, "working-dir", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."},
//{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
//};
//
@@ -701,12 +701,12 @@ protected:
OptionDefinition
CommandObjectProcessAttach::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "continue",'c', no_argument, NULL, 0, eArgTypeNone, "Immediately continue the process once attached."},
-{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
-{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
-{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
-{ LLDB_OPT_SET_2, false, "include-existing", 'i', no_argument, NULL, 0, eArgTypeNone, "Include existing processes when doing attach -w."},
-{ LLDB_OPT_SET_2, false, "waitfor", 'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the process with <process-name> to launch."},
+{ 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 }
};
@@ -891,7 +891,7 @@ protected:
OptionDefinition
CommandObjectProcessContinue::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "ignore-count",'i', required_argument, NULL, 0, eArgTypeUnsignedInteger,
+{ LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, 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 }
};
@@ -1031,7 +1031,7 @@ protected:
OptionDefinition
CommandObjectProcessDetach::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "keep-stopped", 's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." },
+{ 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 }
};
@@ -1203,7 +1203,7 @@ protected:
OptionDefinition
CommandObjectProcessConnect::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
+ { 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 }
};
@@ -1908,9 +1908,9 @@ protected:
OptionDefinition
CommandObjectProcessHandle::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "stop", 's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
-{ LLDB_OPT_SET_1, false, "notify", 'n', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." },
-{ LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
+{ 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 }
};
diff --git a/source/Commands/CommandObjectRegister.cpp b/source/Commands/CommandObjectRegister.cpp
index ba43f23f34ac..7cbfaa5d60fc 100644
--- a/source/Commands/CommandObjectRegister.cpp
+++ b/source/Commands/CommandObjectRegister.cpp
@@ -98,7 +98,7 @@ public:
{
strm.Indent ();
- bool prefix_with_altname = m_command_options.alternate_name;
+ bool prefix_with_altname = (bool)m_command_options.alternate_name;
bool prefix_with_name = !prefix_with_altname;
reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname, m_format_options.GetFormat(), 8);
if ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint))
@@ -192,7 +192,7 @@ protected:
if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx))
{
if (errno)
- result.AppendErrorWithFormat ("register read failed with errno: %d\n", errno);
+ result.AppendErrorWithFormat ("register read failed: %s\n", strerror(errno));
else
result.AppendError ("unknown error while reading registers.\n");
result.SetStatus (eReturnStatusFailed);
@@ -351,9 +351,9 @@ protected:
const OptionDefinition
CommandObjectRegisterRead::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "alternate", 'A', no_argument , NULL, 0, eArgTypeNone , "Display register names using the alternate register name if there is one."},
- { LLDB_OPT_SET_1 , false, "set" , 's', required_argument, NULL, 0, eArgTypeIndex , "Specify which register sets to dump by index."},
- { LLDB_OPT_SET_2 , false, "all" , 'a', no_argument , NULL, 0, eArgTypeNone , "Show all register sets."},
+ { 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."},
};
uint32_t
diff --git a/source/Commands/CommandObjectSettings.cpp b/source/Commands/CommandObjectSettings.cpp
index 95cc9b68a8f7..78a5ad6ca86a 100644
--- a/source/Commands/CommandObjectSettings.cpp
+++ b/source/Commands/CommandObjectSettings.cpp
@@ -288,7 +288,7 @@ private:
OptionDefinition
CommandObjectSettingsSet::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_2, false, "global", 'g', no_argument, NULL, 0, eArgTypeNone, "Apply the new value to the global default value." },
+ { 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 }
};
diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp
index a08e39352b3d..1f6873611a22 100644
--- a/source/Commands/CommandObjectSource.cpp
+++ b/source/Commands/CommandObjectSource.cpp
@@ -137,8 +137,8 @@ protected:
OptionDefinition
CommandObjectSourceInfo::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, "The line number at which to start the display source."},
-{ LLDB_OPT_SET_1, false, "file", 'f', required_argument, 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_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 }
};
@@ -890,15 +890,15 @@ protected:
OptionDefinition
CommandObjectSourceList::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "The number of source lines to display."},
+{ LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "The number of source lines to display."},
{ LLDB_OPT_SET_1 |
- LLDB_OPT_SET_2 , false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source file in the given shared library."},
-{ LLDB_OPT_SET_ALL, false, "show-breakpoints", 'b', no_argument, 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', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source."},
-{ LLDB_OPT_SET_1 , false, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, "The line number at which to start the display source."},
-{ LLDB_OPT_SET_2 , false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display."},
-{ LLDB_OPT_SET_3 , false, "address",'a', required_argument, NULL, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line."},
-{ LLDB_OPT_SET_4, false, "reverse", 'r', no_argument, NULL, 0, eArgTypeNone, "Reverse the listing to look backwards from the last displayed block of source."},
+ 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 }
};
diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp
index dd0e2a0011b0..ef431e25c3d4 100644
--- a/source/Commands/CommandObjectTarget.cpp
+++ b/source/Commands/CommandObjectTarget.cpp
@@ -26,6 +26,7 @@
#include "lldb/Core/State.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -158,6 +159,7 @@ public:
m_arch_option (),
m_platform_options(true), // Do include the "--platform" option in the platform settings by passing true
m_core_file (LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename, "Fullpath to a core file to use for this target."),
+ m_platform_path (LLDB_OPT_SET_1, false, "platform-path", 'P', 0, eArgTypePath, "Path to the remote file to use for this target."),
m_symbol_file (LLDB_OPT_SET_1, false, "symfile", 's', 0, eArgTypeFilename, "Fullpath to a stand alone debug symbols file for when debug symbols are not in the executable."),
m_remote_file (LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename, "Fullpath to the file on the remote host if debugging remotely."),
m_add_dependents (LLDB_OPT_SET_1, false, "no-dependents", 'd', "Don't load dependent files when creating the target, just add the specified executable.", true, true)
@@ -178,6 +180,7 @@ public:
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);
+ m_option_group.Append (&m_platform_path, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Append (&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Append (&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Append (&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
@@ -226,7 +229,7 @@ protected:
FileSpec core_file (m_core_file.GetOptionValue().GetCurrentValue());
FileSpec remote_file (m_remote_file.GetOptionValue().GetCurrentValue());
- if (argc == 1 || core_file)
+ if (argc == 1 || core_file || remote_file)
{
FileSpec symfile (m_symbol_file.GetOptionValue().GetCurrentValue());
if (symfile)
@@ -243,11 +246,70 @@ protected:
const char *file_path = command.GetArgumentAtIndex(0);
Timer scoped_timer(__PRETTY_FUNCTION__, "(lldb) target create '%s'", file_path);
- TargetSP target_sp;
+ 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 ());
+
+ if (remote_file)
+ {
+ // I have a remote file.. two possible cases
+ if (file_spec && file_spec.Exists())
+ {
+ // if the remote file does not exist, push it there
+ if (!platform_sp->GetFileExists (remote_file))
+ {
+ Error err = platform_sp->PutFile(file_spec, remote_file);
+ if (err.Fail())
+ {
+ result.AppendError(err.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // there is no local file and we need one
+ // in order to make the remote ---> local transfer we need a platform
+ // TODO: if the user has passed in a --platform argument, use it to fetch the right platform
+ if (!platform_sp)
+ {
+ result.AppendError("unable to perform remote debugging without a platform");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ if (file_path)
+ {
+ // copy the remote file to the local file
+ Error err = platform_sp->GetFile(remote_file, file_spec);
+ if (err.Fail())
+ {
+ result.AppendError(err.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ // make up a local file
+ result.AppendError("remote --> local transfer without local path is not implemented yet");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ }
+
+ TargetSP target_sp;
const char *arch_cstr = m_arch_option.GetArchitectureName();
const bool get_dependent_files = m_add_dependents.GetOptionValue().GetCurrentValue();
Error error (debugger.GetTargetList().CreateTarget (debugger,
+// remote_file ? remote_file : file_spec,
file_path,
arch_cstr,
get_dependent_files,
@@ -273,6 +335,13 @@ protected:
}
debugger.GetTargetList().SetSelectedTarget(target_sp.get());
+ if (must_set_platform_path)
+ {
+ ModuleSpec main_module_spec(file_spec);
+ ModuleSP module_sp = target_sp->GetSharedModule(main_module_spec);
+ if (module_sp)
+ module_sp->SetPlatformFileSpec(remote_file);
+ }
if (core_file)
{
char core_path[PATH_MAX];
@@ -341,6 +410,7 @@ private:
OptionGroupArchitecture m_arch_option;
OptionGroupPlatform m_platform_options;
OptionGroupFile m_core_file;
+ OptionGroupFile m_platform_path;
OptionGroupFile m_symbol_file;
OptionGroupFile m_remote_file;
OptionGroupBoolean m_add_dependents;
@@ -650,7 +720,7 @@ public:
void
DumpValueObject (Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp, const char *root_name)
{
- ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions());
+ DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions());
switch (var_sp->GetScope())
{
@@ -692,10 +762,7 @@ public:
options.SetRootValueObjectName(root_name);
- ValueObject::DumpValueObject (s,
- valobj_sp.get(),
- options);
-
+ valobj_sp->Dump(s,options);
}
@@ -2214,7 +2281,7 @@ g_sort_option_enumeration[4] =
OptionDefinition
CommandObjectTargetModulesDumpSymtab::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "sort", 's', required_argument, g_sort_option_enumeration, 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol 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 }
};
@@ -2694,6 +2761,8 @@ protected:
module_spec.GetUUID() = m_uuid_option_group.GetOptionValue ().GetCurrentValue();
if (m_symbol_file.GetOptionValue().OptionWasSet())
module_spec.GetSymbolFileSpec() = m_symbol_file.GetOptionValue().GetCurrentValue();
+ if (!module_spec.GetArchitecture().IsValid())
+ module_spec.GetArchitecture() = target->GetArchitecture();
Error error;
ModuleSP module_sp (target->GetSharedModule (module_spec, &error));
if (!module_sp)
@@ -3401,21 +3470,21 @@ protected:
OptionDefinition
CommandObjectTargetModulesList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "address", 'a', required_argument, NULL, 0, eArgTypeAddressOrExpression, "Display the image at this address."},
- { LLDB_OPT_SET_1, false, "arch", 'A', optional_argument, NULL, 0, eArgTypeWidth, "Display the architecture when listing images."},
- { LLDB_OPT_SET_1, false, "triple", 't', optional_argument, NULL, 0, eArgTypeWidth, "Display the triple when listing images."},
- { LLDB_OPT_SET_1, false, "header", 'h', no_argument, 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', no_argument, NULL, 0, eArgTypeNone, "Display the image header address offset from the header file address (the slide amount)."},
- { LLDB_OPT_SET_1, false, "uuid", 'u', no_argument, NULL, 0, eArgTypeNone, "Display the UUID when listing images."},
- { LLDB_OPT_SET_1, false, "fullpath", 'f', optional_argument, NULL, 0, eArgTypeWidth, "Display the fullpath to the image object file."},
- { LLDB_OPT_SET_1, false, "directory", 'd', optional_argument, NULL, 0, eArgTypeWidth, "Display the directory with optional width for the image object file."},
- { LLDB_OPT_SET_1, false, "basename", 'b', optional_argument, NULL, 0, eArgTypeWidth, "Display the basename with optional width for the image object file."},
- { LLDB_OPT_SET_1, false, "symfile", 's', optional_argument, NULL, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width."},
- { LLDB_OPT_SET_1, false, "symfile-unique", 'S', optional_argument, 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', optional_argument, NULL, 0, eArgTypeWidth, "Display the modification time with optional width of the module."},
- { LLDB_OPT_SET_1, false, "ref-count", 'r', optional_argument, NULL, 0, eArgTypeWidth, "Display the reference count if the module is still in the shared module cache."},
- { LLDB_OPT_SET_1, false, "pointer", 'p', optional_argument, NULL, 0, eArgTypeNone, "Display the module pointer."},
- { LLDB_OPT_SET_1, false, "global", 'g', no_argument, NULL, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target."},
+ { 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 }
};
@@ -3468,6 +3537,7 @@ public:
case 'a':
{
ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
+ m_str = option_arg;
m_type = eLookupTypeAddress;
m_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
if (m_addr == LLDB_INVALID_ADDRESS)
@@ -3481,6 +3551,10 @@ public:
m_type = eLookupTypeFunctionOrSymbol;
break;
}
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option %c.", short_option);
+ break;
}
return error;
@@ -3591,8 +3665,21 @@ protected:
}
}
}
+ else
+ {
+ result.AppendError ("address-expression or function name option must be specified.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
size_t num_matches = sc_list.GetSize();
+ if (num_matches == 0)
+ {
+ result.AppendErrorWithFormat ("no unwind data found that matches '%s'.", m_options.m_str.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
for (uint32_t idx = 0; idx < num_matches; idx++)
{
SymbolContext sc;
@@ -3668,8 +3755,8 @@ protected:
OptionDefinition
CommandObjectTargetModulesShowUnwind::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "name", 'n', required_argument, NULL, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name."},
- { LLDB_OPT_SET_2, false, "address", 'a', required_argument, NULL, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address"},
+ { 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 }
};
@@ -4112,21 +4199,21 @@ protected:
OptionDefinition
CommandObjectTargetModulesLookup::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, true, "address", 'a', required_argument, NULL, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules."},
- { LLDB_OPT_SET_1, false, "offset", 'o', required_argument, 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, 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_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', no_argument, NULL, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions."},
- { LLDB_OPT_SET_2, true, "symbol", 's', required_argument, 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', required_argument, NULL, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules."},
- { LLDB_OPT_SET_3, false, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)."},
+ 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)."},
{ LLDB_OPT_SET_FROM_TO(3,5),
- false, "no-inlines", 'i', no_argument, NULL, 0, eArgTypeNone, "Ignore inline entries (must be used in conjunction with --file or --function)."},
- { LLDB_OPT_SET_4, true, "function", 'F', required_argument, 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', required_argument, NULL, 0, eArgTypeFunctionOrSymbol, "Lookup a function or symbol by name in one or more target modules."},
- { LLDB_OPT_SET_6, true, "type", 't', required_argument, 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', no_argument, NULL, 0, eArgTypeNone, "Enable verbose lookup information."},
- { LLDB_OPT_SET_ALL, false, "all", 'A', no_argument, NULL, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available."},
+ 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 }
};
@@ -5062,27 +5149,27 @@ private:
OptionDefinition
CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "one-liner", 'o', required_argument, NULL, 0, eArgTypeOneLiner,
+ { LLDB_OPT_SET_ALL, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOneLiner,
"Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
- { LLDB_OPT_SET_ALL, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
+ { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
"Set the module within which the stop-hook is to be run."},
- { LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, 0, eArgTypeThreadIndex,
+ { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeThreadID,
+ { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeThreadName,
+ { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeQueueName,
+ { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, 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', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeLineNum,
+ { LLDB_OPT_SET_1, false, "start-line", 'l', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeLineNum,
+ { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeClassName,
+ { LLDB_OPT_SET_2, false, "classname", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeClassName,
"Specify the class within which the stop-hook is to be run." },
- { LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
+ { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, 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 }
};
diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp
index b8657b4361d5..f46a2219a509 100644
--- a/source/Commands/CommandObjectThread.cpp
+++ b/source/Commands/CommandObjectThread.cpp
@@ -258,8 +258,8 @@ protected:
OptionDefinition
CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
-{ LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
+{ 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"},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
@@ -591,10 +591,10 @@ g_duo_running_mode[] =
OptionDefinition
CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "avoid-no-debug", 'a', required_argument, 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', required_argument, 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', required_argument, 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', required_argument, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."},
+{ 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 }
};
@@ -660,11 +660,14 @@ public:
StateType state = process->GetState();
if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
{
- Mutex::Locker locker (process->GetThreadList().GetMutex());
- const uint32_t num_threads = process->GetThreadList().GetSize();
const size_t argc = command.GetArgumentCount();
if (argc > 0)
{
+ // These two lines appear at the beginning of both blocks in
+ // this if..else, but that is because we need to release the
+ // lock before calling process->Resume below.
+ Mutex::Locker locker (process->GetThreadList().GetMutex());
+ const uint32_t num_threads = process->GetThreadList().GetSize();
std::vector<Thread *> resume_threads;
for (uint32_t i=0; i<argc; ++i)
{
@@ -674,7 +677,7 @@ public:
if (success)
{
Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get();
-
+
if (thread)
{
resume_threads.push_back(thread);
@@ -693,7 +696,7 @@ public:
return false;
}
}
-
+
if (resume_threads.empty())
{
result.AppendError ("no valid thread indexes were specified");
@@ -706,12 +709,12 @@ public:
result.AppendMessageWithFormat ("Resuming thread: ");
else
result.AppendMessageWithFormat ("Resuming threads: ");
-
+
for (uint32_t idx=0; idx<num_threads; ++idx)
{
Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread);
-
+
if (this_thread_pos != resume_threads.end())
{
resume_threads.erase(this_thread_pos);
@@ -719,7 +722,7 @@ public:
result.AppendMessageWithFormat ("%u, ", thread->GetIndexID());
else
result.AppendMessageWithFormat ("%u ", thread->GetIndexID());
-
+
thread->SetResumeState (eStateRunning);
}
else
@@ -732,6 +735,11 @@ public:
}
else
{
+ // These two lines appear at the beginning of both blocks in
+ // this if..else, but that is because we need to release the
+ // lock before calling process->Resume below.
+ Mutex::Locker locker (process->GetThreadList().GetMutex());
+ const uint32_t num_threads = process->GetThreadList().GetSize();
Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
if (current_thread == NULL)
{
@@ -754,7 +762,8 @@ public:
}
}
}
-
+
+ // We should not be holding the thread list lock when we do this.
Error error (process->Resume());
if (error.Success())
{
@@ -762,7 +771,7 @@ public:
if (synchronous_execution)
{
state = process->WaitForProcessToStop (NULL);
-
+
result.SetDidChangeProcessState (true);
result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
@@ -1120,9 +1129,9 @@ protected:
OptionDefinition
CommandObjectThreadUntil::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"},
-{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"},
-{ LLDB_OPT_SET_1, false, "run-mode",'m', required_argument, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"},
+{ 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 }
};
@@ -1458,11 +1467,213 @@ protected:
OptionDefinition
CommandObjectThreadReturn::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "from-expression", 'x', no_argument, NULL, 0, eArgTypeNone, "Return from the innermost expression evaluation."},
+{ 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 }
};
//-------------------------------------------------------------------------
+// CommandObjectThreadJump
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadJump : public CommandObjectParsed
+{
+public:
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options (interpreter)
+ {
+ OptionParsingStarting ();
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_filenames.Clear();
+ m_line_num = 0;
+ m_line_offset = 0;
+ m_load_addr = LLDB_INVALID_ADDRESS;
+ m_force = false;
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg)
+ {
+ bool success;
+ const int short_option = m_getopt_table[option_idx].val;
+ Error error;
+
+ switch (short_option)
+ {
+ case 'f':
+ m_filenames.AppendIfUnique (FileSpec(option_arg, false));
+ if (m_filenames.GetSize() > 1)
+ return Error("only one source file expected.");
+ break;
+ case 'l':
+ m_line_num = Args::StringToUInt32 (option_arg, 0, 0, &success);
+ if (!success || m_line_num == 0)
+ return Error("invalid line number: '%s'.", option_arg);
+ break;
+ case 'b':
+ m_line_offset = Args::StringToSInt32 (option_arg, 0, 0, &success);
+ if (!success)
+ return Error("invalid line offset: '%s'.", option_arg);
+ break;
+ case 'a':
+ {
+ ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
+ m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
+ }
+ break;
+ case 'r':
+ m_force = true;
+ break;
+
+ default:
+ return Error("invalid short option character '%c'", short_option);
+
+ }
+ return error;
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ FileSpecList m_filenames;
+ uint32_t m_line_num;
+ int32_t m_line_offset;
+ lldb::addr_t m_load_addr;
+ bool m_force;
+
+ static OptionDefinition g_option_table[];
+ };
+
+ virtual
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ CommandObjectThreadJump (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "thread jump",
+ "Sets the program counter to a new address.",
+ "thread jump",
+ eFlagRequiresFrame |
+ eFlagTryTargetAPILock |
+ eFlagProcessMustBeLaunched |
+ eFlagProcessMustBePaused ),
+ m_options (interpreter)
+ {
+ }
+
+ ~CommandObjectThreadJump()
+ {
+ }
+
+protected:
+
+ bool DoExecute (Args& args, CommandReturnObject &result)
+ {
+ RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
+ StackFrame *frame = m_exe_ctx.GetFramePtr();
+ Thread *thread = m_exe_ctx.GetThreadPtr();
+ Target *target = m_exe_ctx.GetTargetPtr();
+ const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry);
+
+ if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
+ {
+ // Use this address directly.
+ Address dest = Address(m_options.m_load_addr);
+
+ lldb::addr_t callAddr = dest.GetCallableLoadAddress (target);
+ if (callAddr == LLDB_INVALID_ADDRESS)
+ {
+ result.AppendErrorWithFormat ("Invalid destination address.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (!reg_ctx->SetPC (callAddr))
+ {
+ result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ // Pick either the absolute line, or work out a relative one.
+ int32_t line = (int32_t)m_options.m_line_num;
+ if (line == 0)
+ line = sym_ctx.line_entry.line + m_options.m_line_offset;
+
+ // Try the current file, but override if asked.
+ FileSpec file = sym_ctx.line_entry.file;
+ if (m_options.m_filenames.GetSize() == 1)
+ file = m_options.m_filenames.GetFileSpecAtIndex(0);
+
+ if (!file)
+ {
+ result.AppendErrorWithFormat ("No source file available for the current location.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ std::string warnings;
+ Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings);
+
+ if (err.Fail())
+ {
+ result.SetError (err);
+ return false;
+ }
+
+ if (!warnings.empty())
+ result.AppendWarning (warnings.c_str());
+ }
+
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ return true;
+ }
+
+ CommandOptions m_options;
+};
+OptionDefinition
+CommandObjectThreadJump::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
+ "Specifies the source file to jump to."},
+
+ { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum,
+ "Specifies the line number to jump to."},
+
+ { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, 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,
+ "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."},
+
+ { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+};
+
+//-------------------------------------------------------------------------
// CommandObjectMultiwordThread
//-------------------------------------------------------------------------
@@ -1476,6 +1687,7 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter)));
LoadSubCommand ("return", CommandObjectSP (new CommandObjectThreadReturn (interpreter)));
+ LoadSubCommand ("jump", CommandObjectSP (new CommandObjectThreadJump (interpreter)));
LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp
index b300f213db0f..1c695b37c566 100644
--- a/source/Commands/CommandObjectType.cpp
+++ b/source/Commands/CommandObjectType.cpp
@@ -369,6 +369,8 @@ private:
m_cascade = true;
m_skip_pointers = false;
m_skip_references = false;
+ m_regex = false;
+ m_category.assign("default");
}
virtual Error
SetOptionValue (CommandInterpreter &interpreter,
@@ -389,9 +391,15 @@ private:
case 'p':
m_skip_pointers = true;
break;
+ case 'w':
+ m_category.assign(option_value);
+ break;
case 'r':
m_skip_references = true;
break;
+ case 'x':
+ m_regex = true;
+ break;
default:
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
break;
@@ -409,6 +417,8 @@ private:
bool m_cascade;
bool m_skip_references;
bool m_skip_pointers;
+ bool m_regex;
+ std::string m_category;
};
OptionGroupOptions m_option_group;
@@ -510,12 +520,32 @@ protected:
// now I have a valid format, let's add it to every type
+ TypeCategoryImplSP category_sp;
+ DataVisualization::Categories::GetCategory(ConstString(m_command_options.m_category), category_sp);
+ if (!category_sp)
+ return false;
+
for (size_t i = 0; i < argc; i++)
{
const char* typeA = command.GetArgumentAtIndex(i);
ConstString typeCS(typeA);
if (typeCS)
- DataVisualization::ValueFormats::Add(typeCS, entry);
+ {
+ if (m_command_options.m_regex)
+ {
+ RegularExpressionSP typeRX(new RegularExpression());
+ if (!typeRX->Compile(typeCS.GetCString()))
+ {
+ result.AppendError("regex format error (maybe this is not really a regex?)");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ category_sp->GetRegexSummaryNavigator()->Delete(typeCS);
+ category_sp->GetRegexValueNavigator()->Add(typeRX, entry);
+ }
+ else
+ category_sp->GetValueNavigator()->Add(typeCS, entry);
+ }
else
{
result.AppendError("empty typenames not allowed");
@@ -532,9 +562,12 @@ protected:
OptionDefinition
CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, 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, "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."},
+ { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
@@ -551,12 +584,89 @@ CommandObjectTypeFormatAdd::CommandOptions::GetNumDefinitions ()
class CommandObjectTypeFormatDelete : public CommandObjectParsed
{
+private:
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options (interpreter)
+ {
+ }
+
+ 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':
+ m_delete_all = true;
+ break;
+ case 'w':
+ m_category = std::string(option_arg);
+ break;
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_delete_all = false;
+ m_category = "default";
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ bool m_delete_all;
+ std::string m_category;
+
+ };
+
+ CommandOptions m_options;
+
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ static bool
+ PerCategoryCallback(void* param,
+ const lldb::TypeCategoryImplSP& category_sp)
+ {
+ ConstString *name = (ConstString*)param;
+ category_sp->Delete(*name, eFormatCategoryItemValue | eFormatCategoryItemRegexValue);
+ return true;
+ }
+
public:
CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"type format delete",
"Delete an existing formatting style for a type.",
- NULL)
+ NULL),
+ m_options(interpreter)
{
CommandArgumentEntry type_arg;
CommandArgumentData type_style_arg;
@@ -597,8 +707,20 @@ protected:
return false;
}
+ if (m_options.m_delete_all)
+ {
+ DataVisualization::Categories::LoopThrough(PerCategoryCallback, &typeCS);
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return result.Succeeded();
+ }
- if (DataVisualization::ValueFormats::Delete(typeCS))
+ lldb::TypeCategoryImplSP category;
+ DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
+
+ bool delete_category = category->Delete(typeCS,
+ eFormatCategoryItemValue | eFormatCategoryItemRegexValue);
+
+ if (delete_category)
{
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
@@ -614,18 +736,100 @@ 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 }
+};
+
//-------------------------------------------------------------------------
// CommandObjectTypeFormatClear
//-------------------------------------------------------------------------
class CommandObjectTypeFormatClear : public CommandObjectParsed
{
+private:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options (interpreter)
+ {
+ }
+
+ 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':
+ m_delete_all = true;
+ break;
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_delete_all = false;
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ bool m_delete_all;
+ bool m_delete_named;
+ };
+
+ CommandOptions m_options;
+
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ static bool
+ PerCategoryCallback(void* param,
+ const lldb::TypeCategoryImplSP& cate)
+ {
+ cate->GetValueNavigator()->Clear();
+ cate->GetRegexValueNavigator()->Clear();
+ return true;
+
+ }
+
public:
CommandObjectTypeFormatClear (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"type format clear",
"Delete all existing format styles.",
- NULL)
+ NULL),
+ m_options(interpreter)
{
}
@@ -637,18 +841,42 @@ protected:
bool
DoExecute (Args& command, CommandReturnObject &result)
{
- DataVisualization::ValueFormats::Clear();
+ if (m_options.m_delete_all)
+ DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL);
+
+ else
+ {
+ lldb::TypeCategoryImplSP category;
+ if (command.GetArgumentCount() > 0)
+ {
+ const char* cat_name = command.GetArgumentAtIndex(0);
+ ConstString cat_nameCS(cat_name);
+ DataVisualization::Categories::GetCategory(cat_nameCS, category);
+ }
+ else
+ DataVisualization::Categories::GetCategory(ConstString(NULL), category);
+ category->Clear(eFormatCategoryItemValue | eFormatCategoryItemRegexValue);
+ }
+
result.SetStatus(eReturnStatusSuccessFinishResult);
return result.Succeeded();
}
};
+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 }
+};
+
//-------------------------------------------------------------------------
// CommandObjectTypeFormatList
//-------------------------------------------------------------------------
bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry);
+bool CommandObjectTypeRXFormatList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeFormatImplSP& entry);
class CommandObjectTypeFormatList;
@@ -656,18 +884,81 @@ struct CommandObjectTypeFormatList_LoopCallbackParam {
CommandObjectTypeFormatList* self;
CommandReturnObject* result;
RegularExpression* regex;
+ RegularExpression* cate_regex;
CommandObjectTypeFormatList_LoopCallbackParam(CommandObjectTypeFormatList* S, CommandReturnObject* R,
- RegularExpression* X = NULL) : self(S), result(R), regex(X) {}
+ RegularExpression* X = NULL, RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
};
class CommandObjectTypeFormatList : public CommandObjectParsed
{
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options (interpreter)
+ {
+ }
+
+ 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 'w':
+ m_category_regex = std::string(option_arg);
+ break;
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_category_regex = "";
+ }
+
+ 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.
+
+ std::string m_category_regex;
+
+ };
+
+ CommandOptions m_options;
+
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
public:
CommandObjectTypeFormatList (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"type format list",
"Show a list of current formatting styles.",
- NULL)
+ NULL),
+ m_options(interpreter)
{
CommandArgumentEntry type_arg;
CommandArgumentData type_style_arg;
@@ -691,38 +982,77 @@ protected:
const size_t argc = command.GetArgumentCount();
CommandObjectTypeFormatList_LoopCallbackParam *param;
+ RegularExpression* cate_regex =
+ m_options.m_category_regex.empty() ? NULL :
+ new RegularExpression(m_options.m_category_regex.c_str());
if (argc == 1)
{
RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
regex->Compile(command.GetArgumentAtIndex(0));
- param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,regex);
+ param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,regex,cate_regex);
}
else
- param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result);
- DataVisualization::ValueFormats::LoopThrough(CommandObjectTypeFormatList_LoopCallback, param);
- delete param;
+ param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,NULL,cate_regex);
+
+ DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
+
+ if (cate_regex)
+ delete cate_regex;
+
result.SetStatus(eReturnStatusSuccessFinishResult);
return result.Succeeded();
}
private:
+ static bool
+ PerCategoryCallback(void* param_vp,
+ const lldb::TypeCategoryImplSP& cate)
+ {
+
+ CommandObjectTypeFormatList_LoopCallbackParam* param =
+ (CommandObjectTypeFormatList_LoopCallbackParam*)param_vp;
+ CommandReturnObject* result = param->result;
+
+ const char* cate_name = cate->GetName();
+
+ // if the category is disabled or empty and there is no regex, just skip it
+ if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemValue | eFormatCategoryItemRegexValue) == 0) && param->cate_regex == NULL)
+ return true;
+
+ // if we have a regex and this category does not match it, just skip it
+ if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false)
+ return true;
+
+ result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
+ cate_name,
+ (cate->IsEnabled() ? "enabled" : "disabled"));
+
+ cate->GetValueNavigator()->LoopThrough(CommandObjectTypeFormatList_LoopCallback, param_vp);
+
+ if (cate->GetRegexSummaryNavigator()->GetCount() > 0)
+ {
+ result->GetOutputStream().Printf("Regex-based summaries (slower):\n");
+ cate->GetRegexValueNavigator()->LoopThrough(CommandObjectTypeRXFormatList_LoopCallback, param_vp);
+ }
+ return true;
+ }
+
+
bool
- LoopCallback (ConstString type,
+ LoopCallback (const char* type,
const lldb::TypeFormatImplSP& entry,
RegularExpression* regex,
CommandReturnObject *result)
{
- if (regex == NULL || regex->Execute(type.AsCString()))
- {
- result->GetOutputStream().Printf ("%s: %s\n", type.AsCString(),
- entry->GetDescription().c_str());
- }
+ if (regex == NULL || strcmp(type,regex->GetText()) == 0 || regex->Execute(type))
+ result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
return true;
}
friend bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry);
+ friend bool CommandObjectTypeRXFormatList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeFormatImplSP& entry);
};
@@ -733,9 +1063,25 @@ CommandObjectTypeFormatList_LoopCallback (
const lldb::TypeFormatImplSP& entry)
{
CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self;
- return param->self->LoopCallback(type, entry, param->regex, param->result);
+ return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
+}
+
+bool
+CommandObjectTypeRXFormatList_LoopCallback (
+ void* pt2self,
+ lldb::RegularExpressionSP regex,
+ const lldb::TypeFormatImplSP& entry)
+{
+ CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self;
+ return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
}
+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 }
+};
#ifndef LLDB_DISABLE_PYTHON
@@ -1395,20 +1741,20 @@ CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
OptionDefinition
CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
- { LLDB_OPT_SET_ALL, false, "no-value", 'v', no_argument, NULL, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type."},
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
- { LLDB_OPT_SET_1 , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeNone, "If true, inline all child values into summary string."},
- { LLDB_OPT_SET_1 , false, "omit-names", 'O', no_argument, NULL, 0, eArgTypeNone, "If true, omit value names in the summary display."},
- { LLDB_OPT_SET_2 , true, "summary-string", 's', required_argument, NULL, 0, eArgTypeSummaryString, "Summary string used to display text and object contents."},
- { LLDB_OPT_SET_3, false, "python-script", 'o', required_argument, NULL, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command."},
- { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type."},
- { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."},
- { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', no_argument, NULL, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines."},
- { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."},
+ { 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 }
};
@@ -1574,8 +1920,8 @@ protected:
OptionDefinition
CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Delete from every category."},
- { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."},
+ { 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 }
};
@@ -1701,7 +2047,7 @@ protected:
OptionDefinition
CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Clear every category."},
+ { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Clear every category."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
@@ -1929,7 +2275,7 @@ CommandObjectTypeRXSummaryList_LoopCallback (
OptionDefinition
CommandObjectTypeSummaryList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
+ { 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 }
};
@@ -2476,7 +2822,7 @@ CommandObjectTypeFilterRXList_LoopCallback (void* pt2self,
OptionDefinition
CommandObjectTypeFilterList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
+ { 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 }
};
@@ -2690,7 +3036,7 @@ CommandObjectTypeSynthRXList_LoopCallback (void* pt2self,
OptionDefinition
CommandObjectTypeSynthList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
+ { 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 }
};
@@ -2854,8 +3200,8 @@ protected:
OptionDefinition
CommandObjectTypeFilterDelete::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Delete from every category."},
- { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."},
+ { 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 }
};
@@ -3020,8 +3366,8 @@ protected:
OptionDefinition
CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Delete from every category."},
- { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."},
+ { 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 }
};
@@ -3151,7 +3497,7 @@ protected:
OptionDefinition
CommandObjectTypeFilterClear::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Clear every category."},
+ { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Clear every category."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
@@ -3280,7 +3626,7 @@ protected:
OptionDefinition
CommandObjectTypeSynthClear::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Clear every category."},
+ { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Clear every category."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
@@ -3663,13 +4009,13 @@ CommandObjectTypeSynthAdd::DoExecute (Args& command, CommandReturnObject &result
OptionDefinition
CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
- { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."},
- { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."},
- { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
+ { 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 }
};
@@ -3967,12 +4313,12 @@ protected:
OptionDefinition
CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
- { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view."},
- { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
+ { 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 }
};
diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp
index 6f70f39c1c71..ae490e38149e 100644
--- a/source/Commands/CommandObjectWatchpoint.cpp
+++ b/source/Commands/CommandObjectWatchpoint.cpp
@@ -335,13 +335,13 @@ private:
OptionDefinition
CommandObjectWatchpointList::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "brief", 'b', no_argument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
"Give a brief description of the watchpoint (no location info)."},
- { LLDB_OPT_SET_2, false, "full", 'f', no_argument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
"Give a full description of the watchpoint and its locations."},
- { LLDB_OPT_SET_3, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone,
+ { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
"Explain everything we know about the watchpoint (for debugging debugger bugs)." },
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
@@ -397,7 +397,7 @@ protected:
{
// No watchpoint selected; enable all currently set watchpoints.
target->EnableAllWatchpoints();
- result.AppendMessageWithFormat("All watchpoints enabled. (%lu watchpoints)\n", num_watchpoints);
+ result.AppendMessageWithFormat("All watchpoints enabled. (%zu watchpoints)\n", num_watchpoints);
result.SetStatus(eReturnStatusSuccessFinishNoResult);
}
else
@@ -476,7 +476,7 @@ protected:
// No watchpoint selected; disable all currently set watchpoints.
if (target->DisableAllWatchpoints())
{
- result.AppendMessageWithFormat("All watchpoints disabled. (%lu watchpoints)\n", num_watchpoints);
+ result.AppendMessageWithFormat("All watchpoints disabled. (%zu watchpoints)\n", num_watchpoints);
result.SetStatus(eReturnStatusSuccessFinishNoResult);
}
else
@@ -564,7 +564,7 @@ protected:
else
{
target->RemoveAllWatchpoints();
- result.AppendMessageWithFormat("All watchpoints removed. (%lu watchpoints)\n", num_watchpoints);
+ result.AppendMessageWithFormat("All watchpoints removed. (%zu watchpoints)\n", num_watchpoints);
}
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
@@ -706,7 +706,7 @@ protected:
if (command.GetArgumentCount() == 0)
{
target->IgnoreAllWatchpoints(m_options.m_ignore_count);
- result.AppendMessageWithFormat("All watchpoints ignored. (%lu watchpoints)\n", num_watchpoints);
+ result.AppendMessageWithFormat("All watchpoints ignored. (%zu watchpoints)\n", num_watchpoints);
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
@@ -740,7 +740,7 @@ private:
OptionDefinition
CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', required_argument, NULL, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." },
+ { 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 }
};
@@ -903,7 +903,7 @@ private:
OptionDefinition
CommandObjectWatchpointModify::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "condition", 'c', required_argument, NULL, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."},
+{ 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 }
};
@@ -1099,7 +1099,7 @@ protected:
}
else
{
- result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%lu, variable expression='%s').\n",
+ result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%zu, variable expression='%s').\n",
addr, size, command.GetArgumentAtIndex(0));
if (error.AsCString(NULL))
result.AppendError(error.AsCString());
@@ -1308,7 +1308,7 @@ protected:
}
else
{
- result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%lu).\n",
+ result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%zu).\n",
addr, size);
if (error.AsCString(NULL))
result.AppendError(error.AsCString());
diff --git a/source/Commands/CommandObjectWatchpointCommand.cpp b/source/Commands/CommandObjectWatchpointCommand.cpp
index 4e200465031d..e19216d74fce 100644
--- a/source/Commands/CommandObjectWatchpointCommand.cpp
+++ b/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -601,16 +601,16 @@ g_script_option_enumeration[4] =
OptionDefinition
CommandObjectWatchpointCommandAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "one-liner", 'o', required_argument, NULL, 0, eArgTypeOneLiner,
+ { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypeBoolean,
+ { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
"Specify whether watchpoint command execution should terminate on error." },
- { LLDB_OPT_SET_ALL, false, "script-type", 's', required_argument, g_script_option_enumeration, 0, eArgTypeNone,
+ { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, 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', required_argument, NULL, 0, eArgTypePythonFunction,
+ { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, 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 }
diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp
index 8d599d80ad4f..1e79f332ffc8 100644
--- a/source/Core/Address.cpp
+++ b/source/Core/Address.cpp
@@ -12,7 +12,6 @@
#include "lldb/Core/Section.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
@@ -281,6 +280,12 @@ Address::GetFileAddress () const
// address by adding the file base address to our offset
return sect_file_addr + m_offset;
}
+ else if (SectionWasDeleted())
+ {
+ // Used to have a valid section but it got deleted so the
+ // offset doesn't mean anything without the section
+ return LLDB_INVALID_ADDRESS;
+ }
// No section, we just return the offset since it is the value in this case
return m_offset;
}
@@ -289,25 +294,33 @@ addr_t
Address::GetLoadAddress (Target *target) const
{
SectionSP section_sp (GetSection());
- if (!section_sp)
- {
- // No section, we just return the offset since it is the value in this case
- return m_offset;
- }
-
- if (target)
+ if (section_sp)
{
- addr_t sect_load_addr = section_sp->GetLoadBaseAddress (target);
-
- if (sect_load_addr != LLDB_INVALID_ADDRESS)
+ if (target)
{
- // We have a valid file range, so we can return the file based
- // address by adding the file base address to our offset
- return sect_load_addr + m_offset;
+ addr_t sect_load_addr = section_sp->GetLoadBaseAddress (target);
+
+ if (sect_load_addr != LLDB_INVALID_ADDRESS)
+ {
+ // We have a valid file range, so we can return the file based
+ // address by adding the file base address to our offset
+ return sect_load_addr + m_offset;
+ }
}
}
- // The section isn't resolved or no process was supplied so we can't
- // return a valid file address.
+ else if (SectionWasDeleted())
+ {
+ // Used to have a valid section but it got deleted so the
+ // offset doesn't mean anything without the section
+ return LLDB_INVALID_ADDRESS;
+ }
+ else
+ {
+ // We don't have a section so the offset is the load address
+ return m_offset;
+ }
+ // The section isn't resolved or an invalid target was passed in
+ // so we can't return a valid load address.
return LLDB_INVALID_ADDRESS;
}
@@ -767,6 +780,19 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
return true;
}
+bool
+Address::SectionWasDeleted() const
+{
+ lldb::SectionWP empty_section_wp;
+
+ // If either call to "std::weak_ptr::owner_before(...) value returns true, this
+ // indicates that m_section_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 unloaded/deleted,
+ // or if the address doesn't have a valid reference to a section.
+ return empty_section_wp.owner_before(m_section_wp) || m_section_wp.owner_before(empty_section_wp);
+}
+
uint32_t
Address::CalculateSymbolContext (SymbolContext *sc, uint32_t resolve_scope) const
{
diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp
index 27d62c358bbf..f2eb3751a4b5 100644
--- a/source/Core/ArchSpec.cpp
+++ b/source/Core/ArchSpec.cpp
@@ -14,6 +14,7 @@
#include <string>
+#include "llvm/Support/COFF.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MachO.h"
@@ -55,6 +56,7 @@ static const CoreDefinition g_core_definitions[ArchSpec::kNumCores] =
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv5e , "armv5e" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv5t , "armv5t" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv6 , "armv6" },
+ { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv6m , "armv6m" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv7 , "armv7" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv7f , "armv7f" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv7s , "armv7s" },
@@ -67,13 +69,15 @@ static const CoreDefinition g_core_definitions[ArchSpec::kNumCores] =
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv5 , "thumbv5" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv5e , "thumbv5e" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv6 , "thumbv6" },
+ { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv6m , "thumbv6m" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv7 , "thumbv7" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv7f , "thumbv7f" },
{ eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv7s , "thumbv7s" },
{ 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" },
-
+
+ { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64 , "mips64" },
{ eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_generic , "ppc" },
{ eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc601 , "ppc601" },
@@ -154,58 +158,60 @@ ArchSpec::AutoComplete (const char *name, StringList &matches)
#define SUBTYPE_MASK 0x00FFFFFFu
static const ArchDefinitionEntry g_macho_arch_entries[] =
{
- { ArchSpec::eCore_arm_generic , llvm::MachO::CPUTypeARM , CPU_ANY, UINT32_MAX , UINT32_MAX },
- { ArchSpec::eCore_arm_generic , llvm::MachO::CPUTypeARM , 0 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_armv4 , llvm::MachO::CPUTypeARM , 5 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_armv4t , llvm::MachO::CPUTypeARM , 5 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_armv6 , llvm::MachO::CPUTypeARM , 6 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_armv5 , llvm::MachO::CPUTypeARM , 7 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_armv5e , llvm::MachO::CPUTypeARM , 7 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_armv5t , llvm::MachO::CPUTypeARM , 7 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_xscale , llvm::MachO::CPUTypeARM , 8 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_armv7 , llvm::MachO::CPUTypeARM , 9 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_armv7f , llvm::MachO::CPUTypeARM , 10 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_armv7s , llvm::MachO::CPUTypeARM , 11 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_armv7k , llvm::MachO::CPUTypeARM , 12 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_armv7m , llvm::MachO::CPUTypeARM , 15 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_arm_armv7em , llvm::MachO::CPUTypeARM , 16 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_thumb , llvm::MachO::CPUTypeARM , 0 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_thumbv4t , llvm::MachO::CPUTypeARM , 5 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_thumbv5 , llvm::MachO::CPUTypeARM , 7 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_thumbv5e , llvm::MachO::CPUTypeARM , 7 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_thumbv6 , llvm::MachO::CPUTypeARM , 6 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_thumbv7 , llvm::MachO::CPUTypeARM , 9 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_thumbv7f , llvm::MachO::CPUTypeARM , 10 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_thumbv7s , llvm::MachO::CPUTypeARM , 11 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_thumbv7k , llvm::MachO::CPUTypeARM , 12 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_thumbv7m , llvm::MachO::CPUTypeARM , 15 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_thumbv7em , llvm::MachO::CPUTypeARM , 16 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_generic , llvm::MachO::CPUTypePowerPC , CPU_ANY, UINT32_MAX , UINT32_MAX },
- { ArchSpec::eCore_ppc_generic , llvm::MachO::CPUTypePowerPC , 0 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_ppc601 , llvm::MachO::CPUTypePowerPC , 1 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_ppc602 , llvm::MachO::CPUTypePowerPC , 2 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_ppc603 , llvm::MachO::CPUTypePowerPC , 3 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_ppc603e , llvm::MachO::CPUTypePowerPC , 4 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_ppc603ev , llvm::MachO::CPUTypePowerPC , 5 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_ppc604 , llvm::MachO::CPUTypePowerPC , 6 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_ppc604e , llvm::MachO::CPUTypePowerPC , 7 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_ppc620 , llvm::MachO::CPUTypePowerPC , 8 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_ppc750 , llvm::MachO::CPUTypePowerPC , 9 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_ppc7400 , llvm::MachO::CPUTypePowerPC , 10 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_ppc7450 , llvm::MachO::CPUTypePowerPC , 11 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc_ppc970 , llvm::MachO::CPUTypePowerPC , 100 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc64_generic , llvm::MachO::CPUTypePowerPC64 , 0 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_ppc64_ppc970_64 , llvm::MachO::CPUTypePowerPC64 , 100 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_x86_32_i386 , llvm::MachO::CPUTypeI386 , 3 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_x86_32_i486 , llvm::MachO::CPUTypeI386 , 4 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_x86_32_i486sx , llvm::MachO::CPUTypeI386 , 0x84 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_x86_32_i386 , llvm::MachO::CPUTypeI386 , CPU_ANY, UINT32_MAX , UINT32_MAX },
- { ArchSpec::eCore_x86_64_x86_64 , llvm::MachO::CPUTypeX86_64 , 3 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_x86_64_x86_64 , llvm::MachO::CPUTypeX86_64 , 4 , UINT32_MAX , SUBTYPE_MASK },
- { ArchSpec::eCore_x86_64_x86_64 , llvm::MachO::CPUTypeX86_64 , CPU_ANY, UINT32_MAX , UINT32_MAX },
+ { ArchSpec::eCore_arm_generic , llvm::MachO::CPU_TYPE_ARM , CPU_ANY, UINT32_MAX , UINT32_MAX },
+ { ArchSpec::eCore_arm_generic , llvm::MachO::CPU_TYPE_ARM , 0 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_arm_armv4 , llvm::MachO::CPU_TYPE_ARM , 5 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_arm_armv4t , llvm::MachO::CPU_TYPE_ARM , 5 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_arm_armv6 , llvm::MachO::CPU_TYPE_ARM , 6 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_arm_armv6m , llvm::MachO::CPU_TYPE_ARM , 14 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_arm_armv5 , llvm::MachO::CPU_TYPE_ARM , 7 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_arm_armv5e , llvm::MachO::CPU_TYPE_ARM , 7 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_arm_armv5t , llvm::MachO::CPU_TYPE_ARM , 7 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_arm_xscale , llvm::MachO::CPU_TYPE_ARM , 8 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_arm_armv7 , llvm::MachO::CPU_TYPE_ARM , 9 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_arm_armv7f , llvm::MachO::CPU_TYPE_ARM , 10 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_arm_armv7s , llvm::MachO::CPU_TYPE_ARM , 11 , UINT32_MAX , SUBTYPE_MASK },
+ { 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_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 },
+ { ArchSpec::eCore_thumbv5e , llvm::MachO::CPU_TYPE_ARM , 7 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_thumbv6 , llvm::MachO::CPU_TYPE_ARM , 6 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_thumbv6m , llvm::MachO::CPU_TYPE_ARM , 14 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_thumbv7 , llvm::MachO::CPU_TYPE_ARM , 9 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_thumbv7f , llvm::MachO::CPU_TYPE_ARM , 10 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_thumbv7s , llvm::MachO::CPU_TYPE_ARM , 11 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_thumbv7k , llvm::MachO::CPU_TYPE_ARM , 12 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_thumbv7m , llvm::MachO::CPU_TYPE_ARM , 15 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_thumbv7em , llvm::MachO::CPU_TYPE_ARM , 16 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_generic , llvm::MachO::CPU_TYPE_POWERPC , CPU_ANY, UINT32_MAX , UINT32_MAX },
+ { ArchSpec::eCore_ppc_generic , llvm::MachO::CPU_TYPE_POWERPC , 0 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_ppc601 , llvm::MachO::CPU_TYPE_POWERPC , 1 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_ppc602 , llvm::MachO::CPU_TYPE_POWERPC , 2 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_ppc603 , llvm::MachO::CPU_TYPE_POWERPC , 3 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_ppc603e , llvm::MachO::CPU_TYPE_POWERPC , 4 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_ppc603ev , llvm::MachO::CPU_TYPE_POWERPC , 5 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_ppc604 , llvm::MachO::CPU_TYPE_POWERPC , 6 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_ppc604e , llvm::MachO::CPU_TYPE_POWERPC , 7 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_ppc620 , llvm::MachO::CPU_TYPE_POWERPC , 8 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_ppc750 , llvm::MachO::CPU_TYPE_POWERPC , 9 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_ppc7400 , llvm::MachO::CPU_TYPE_POWERPC , 10 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_ppc7450 , llvm::MachO::CPU_TYPE_POWERPC , 11 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc_ppc970 , llvm::MachO::CPU_TYPE_POWERPC , 100 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc64_generic , llvm::MachO::CPU_TYPE_POWERPC64 , 0 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_ppc64_ppc970_64 , llvm::MachO::CPU_TYPE_POWERPC64 , 100 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_x86_32_i386 , llvm::MachO::CPU_TYPE_I386 , 3 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_x86_32_i486 , llvm::MachO::CPU_TYPE_I386 , 4 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_x86_32_i486sx , llvm::MachO::CPU_TYPE_I386 , 0x84 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_x86_32_i386 , llvm::MachO::CPU_TYPE_I386 , CPU_ANY, UINT32_MAX , UINT32_MAX },
+ { ArchSpec::eCore_x86_64_x86_64 , llvm::MachO::CPU_TYPE_X86_64 , 3 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_x86_64_x86_64 , llvm::MachO::CPU_TYPE_X86_64 , 4 , UINT32_MAX , SUBTYPE_MASK },
+ { ArchSpec::eCore_x86_64_x86_64 , llvm::MachO::CPU_TYPE_X86_64 , CPU_ANY, UINT32_MAX , UINT32_MAX },
// Catch any unknown mach architectures so we can always use the object and symbol mach-o files
- { ArchSpec::eCore_uknownMach32 , 0 , 0 , 0xFF000000u, 0x00000000u },
- { ArchSpec::eCore_uknownMach64 , llvm::MachO::CPUArchABI64 , 0 , 0xFF000000u, 0x00000000u }
+ { ArchSpec::eCore_uknownMach32 , 0 , 0 , 0xFF000000u, 0x00000000u },
+ { ArchSpec::eCore_uknownMach64 , llvm::MachO::CPU_ARCH_ABI64 , 0 , 0xFF000000u, 0x00000000u }
};
static const ArchDefinition g_macho_arch_def = {
eArchTypeMachO,
@@ -228,7 +234,8 @@ static const ArchDefinitionEntry g_elf_arch_entries[] =
{ 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_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_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
};
static const ArchDefinition g_elf_arch_def = {
@@ -238,11 +245,30 @@ static const ArchDefinition g_elf_arch_def = {
"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_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_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]),
+ g_coff_arch_entries,
+ "pe-coff",
+};
+
//===----------------------------------------------------------------------===//
// Table of all ArchDefinitions
static const ArchDefinition *g_arch_definitions[] = {
&g_macho_arch_def,
- &g_elf_arch_def
+ &g_elf_arch_def,
+ &g_coff_arch_def
};
static const size_t k_num_arch_definitions =
@@ -863,6 +889,15 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
return true;
break;
+ case ArchSpec::eCore_arm_armv6m:
+ if (!enforce_exact_match)
+ {
+ try_inverse = false;
+ if (core2 == ArchSpec::eCore_arm_armv7)
+ return true;
+ }
+ break;
+
case ArchSpec::eCore_arm_armv7m:
case ArchSpec::eCore_arm_armv7em:
case ArchSpec::eCore_arm_armv7f:
diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp
index 7f40e6520204..6ea7a11426be 100644
--- a/source/Core/Communication.cpp
+++ b/source/Core/Communication.cpp
@@ -333,8 +333,8 @@ Communication::ReadThreadIsRunning ()
return m_read_thread_enabled;
}
-void *
-Communication::ReadThread (void *p)
+lldb::thread_result_t
+Communication::ReadThread (lldb::thread_arg_t p)
{
Communication *comm = (Communication *)p;
diff --git a/source/Core/ConnectionFileDescriptor.cpp b/source/Core/ConnectionFileDescriptor.cpp
index e320bda2fcdc..8e80543b857b 100644
--- a/source/Core/ConnectionFileDescriptor.cpp
+++ b/source/Core/ConnectionFileDescriptor.cpp
@@ -15,10 +15,16 @@
#endif
#include "lldb/Core/ConnectionFileDescriptor.h"
+#include "lldb/Host/Config.h"
+#include "lldb/Host/SocketAddress.h"
// C Includes
#include <errno.h>
#include <fcntl.h>
+#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>
@@ -26,13 +32,17 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <termios.h>
-#include <sys/types.h>
-#include <string.h>
-#include <stdlib.h>
#include <unistd.h>
+#endif
+#ifdef _WIN32
+#include "lldb/Host/windows/windows.h"
+#include <winsock2.h>
+#include <WS2tcpip.h>
+#endif
// C++ Includes
// Other libraries and framework includes
+#include "llvm/Support/ErrorHandling.h"
#if defined(__APPLE__)
#include "llvm/ADT/SmallVector.h"
#endif
@@ -84,7 +94,7 @@ ConnectionFileDescriptor::ConnectionFileDescriptor () :
m_fd_recv (-1),
m_fd_send_type (eFDTypeFile),
m_fd_recv_type (eFDTypeFile),
- m_udp_send_sockaddr (),
+ m_udp_send_sockaddr (new SocketAddress()),
m_should_close_fd (false),
m_socket_timeout_usec(0),
m_pipe_read(-1),
@@ -103,7 +113,7 @@ ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) :
m_fd_recv (fd),
m_fd_send_type (eFDTypeFile),
m_fd_recv_type (eFDTypeFile),
- m_udp_send_sockaddr (),
+ m_udp_send_sockaddr (new SocketAddress()),
m_should_close_fd (owns_fd),
m_socket_timeout_usec(0),
m_pipe_read(-1),
@@ -135,11 +145,15 @@ ConnectionFileDescriptor::OpenCommandPipe ()
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 (log)
- log->Printf ("%p ConnectionFileDescriptor::ConnectionFileDescriptor () - could not make pipe: %s",
+ log->Printf ("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s",
this,
strerror(errno));
}
@@ -147,21 +161,39 @@ ConnectionFileDescriptor::OpenCommandPipe ()
{
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);
}
}
void
ConnectionFileDescriptor::CloseCommandPipe ()
{
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("%p ConnectionFileDescriptor::CloseCommandPipe()",
+ 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;
}
}
@@ -223,7 +255,11 @@ 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
if (flags == -1 || errno == EBADF)
{
if (error_ptr)
@@ -262,6 +298,7 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
{
// file:///PATH
const char *path = s + strlen("file://");
+#ifndef LLDB_DISABLE_POSIX
do
{
m_fd_send = m_fd_recv = ::open (path, O_RDWR);
@@ -304,6 +341,9 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
}
m_should_close_fd = true;
return eConnectionStatusSuccess;
+#else
+ return eConnectionStatusError;
+#endif
}
if (error_ptr)
error_ptr->SetErrorStringWithFormat ("unsupported connection URL: '%s'", s);
@@ -344,27 +384,30 @@ ConnectionFileDescriptor::Disconnect (Error *error_ptr)
{
if (m_pipe_write != -1 )
{
- write (m_pipe_write, "q", 1);
- close (m_pipe_write);
- m_pipe_write = -1;
+ int result;
+ result = write (m_pipe_write, "q", 1);
+ if (log)
+ log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, sent 'q' to %d, result = %d.", this, m_pipe_write, 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, error_ptr);
+ 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, error_ptr);
+ status = Close (m_fd_send, m_fd_send_type, error_ptr);
if (m_fd_recv >= 0)
{
- ConnectionStatus recv_status = Close (m_fd_recv, error_ptr);
+ ConnectionStatus recv_status = Close (m_fd_recv, m_fd_recv_type, error_ptr);
if (status == eConnectionStatusSuccess)
status = recv_status;
}
@@ -420,7 +463,21 @@ ConnectionFileDescriptor::Read (void *dst,
{
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);
}
@@ -494,6 +551,13 @@ ConnectionFileDescriptor::Read (void *dst,
case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket.
status = eConnectionStatusTimedOut;
return 0;
+
+ default:
+ if (log)
+ log->Printf("%p ConnectionFileDescriptor::Read (), unexpected error: %s", this, strerror(error_value));
+ status = eConnectionStatusError;
+ break; // Break to close....
+
}
return 0;
@@ -523,30 +587,31 @@ ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStat
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, src, src_len, 0);
+ 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);
+ assert (m_udp_send_sockaddr->GetFamily() != 0);
do
{
bytes_sent = ::sendto (m_fd_send,
- src,
+ (char*)src,
src_len,
0,
- m_udp_send_sockaddr,
- m_udp_send_sockaddr.GetLength());
+ *m_udp_send_sockaddr,
+ m_udp_send_sockaddr->GetLength());
} while (bytes_sent < 0 && errno == EINTR);
break;
}
@@ -656,7 +721,8 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt
{
TimeValue time_value;
time_value.OffsetWithMicroSeconds (timeout_usec);
- tv = time_value.GetAsTimeVal();
+ tv.tv_sec = time_value.seconds();
+ tv.tv_usec = time_value.microseconds();
tv_ptr = &tv;
}
@@ -806,7 +872,8 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt
{
TimeValue time_value;
time_value.OffsetWithMicroSeconds (timeout_usec);
- tv = time_value.GetAsTimeVal();
+ tv.tv_sec = time_value.seconds();
+ tv.tv_usec = time_value.microseconds();
tv_ptr = &tv;
}
@@ -821,7 +888,9 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt
// 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;
@@ -1077,7 +1146,7 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt
#endif
ConnectionStatus
-ConnectionFileDescriptor::Close (int& fd, Error *error_ptr)
+ConnectionFileDescriptor::Close (int& fd, FDType type, Error *error_ptr)
{
if (error_ptr)
error_ptr->Clear();
@@ -1093,7 +1162,11 @@ ConnectionFileDescriptor::Close (int& fd, Error *error_ptr)
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;
@@ -1115,6 +1188,7 @@ ConnectionFileDescriptor::Close (int& fd, Error *error_ptr)
ConnectionStatus
ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *error_ptr)
{
+#ifndef LLDB_DISABLE_POSIX
ConnectionStatus result = eConnectionStatusError;
struct sockaddr_un saddr_un;
@@ -1131,7 +1205,7 @@ ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *err
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__)
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
saddr_un.sun_len = SUN_LEN (&saddr_un);
#endif
@@ -1157,13 +1231,17 @@ ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *err
error_ptr->SetErrorToErrno();
}
// We are done with the listen port
- Close (listen_socket, NULL);
+ Close (listen_socket, eFDTypeSocket, NULL);
return result;
+#else
+ return eConnectionStatusError;
+#endif
}
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;
@@ -1180,7 +1258,7 @@ ConnectionFileDescriptor::NamedSocketConnect (const char *socket_name, Error *er
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__)
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
saddr_un.sun_len = SUN_LEN (&saddr_un);
#endif
@@ -1194,6 +1272,9 @@ ConnectionFileDescriptor::NamedSocketConnect (const char *socket_name, Error *er
if (error_ptr)
error_ptr->Clear();
return eConnectionStatusSuccess;
+#else
+ return eConnectionStatusError;
+#endif
}
ConnectionStatus
@@ -1224,7 +1305,7 @@ ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_p
{
if (error_ptr)
error_ptr->SetErrorToErrno();
- Close (listen_port, NULL);
+ Close (listen_port, eFDTypeSocket, NULL);
return eConnectionStatusError;
}
@@ -1233,7 +1314,7 @@ ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_p
{
if (error_ptr)
error_ptr->SetErrorToErrno();
- Close (listen_port, NULL);
+ Close (listen_port, eFDTypeSocket, NULL);
return eConnectionStatusError;
}
@@ -1242,13 +1323,13 @@ ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_p
{
if (error_ptr)
error_ptr->SetErrorToErrno();
- Close (listen_port, NULL);
+ Close (listen_port, eFDTypeSocket, NULL);
return eConnectionStatusError;
}
}
// We are done with the listen port
- Close (listen_port, NULL);
+ Close (listen_port, eFDTypeSocket, NULL);
m_should_close_fd = true;
@@ -1408,7 +1489,7 @@ ConnectionFileDescriptor::ConnectUDP (const char *host_and_port, Error *error_pt
if (m_fd_send != -1)
{
- m_udp_send_sockaddr = service_info_ptr;
+ *m_udp_send_sockaddr = service_info_ptr;
break;
}
else
@@ -1430,18 +1511,18 @@ ConnectionFileDescriptor::ConnectUDP (const char *host_and_port, Error *error_pt
return eConnectionStatusSuccess;
}
-#if defined(__MINGW32__) || defined(__MINGW64__)
+#if defined(_WIN32)
typedef const char * set_socket_option_arg_type;
typedef char * get_socket_option_arg_type;
-#else // #if defined(__MINGW32__) || defined(__MINGW64__)
+#else // #if defined(_WIN32)
typedef const void * set_socket_option_arg_type;
typedef void * get_socket_option_arg_type;
-#endif // #if defined(__MINGW32__) || defined(__MINGW64__)
+#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 = static_cast<get_socket_option_arg_type>(&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);
}
@@ -1449,7 +1530,7 @@ ConnectionFileDescriptor::GetSocketOption(int fd, int level, int option_name, in
int
ConnectionFileDescriptor::SetSocketOption(int fd, int level, int option_name, int option_value)
{
- set_socket_option_arg_type option_value_p = static_cast<get_socket_option_arg_type>(&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));
}
@@ -1487,7 +1568,7 @@ ConnectionFileDescriptor::SetSocketReceiveTimeout (uint32_t timeout_usec)
timeout.tv_sec = timeout_usec / TimeValue::MicroSecPerSec;
timeout.tv_usec = timeout_usec % TimeValue::MicroSecPerSec;
}
- if (::setsockopt (m_fd_recv, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0)
+ 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;
diff --git a/source/Core/ConnectionMachPort.cpp b/source/Core/ConnectionMachPort.cpp
index ca818d405a20..4a090dbe5ec8 100644
--- a/source/Core/ConnectionMachPort.cpp
+++ b/source/Core/ConnectionMachPort.cpp
@@ -11,6 +11,7 @@
#include "lldb/Core/ConnectionMachPort.h"
// C Includes
+#include <mach/mach.h>
#include <servers/bootstrap.h>
// C++ Includes
diff --git a/source/Core/ConnectionSharedMemory.cpp b/source/Core/ConnectionSharedMemory.cpp
index 625f17a0985b..cd708c4868c9 100644
--- a/source/Core/ConnectionSharedMemory.cpp
+++ b/source/Core/ConnectionSharedMemory.cpp
@@ -11,12 +11,15 @@
// C Includes
#include <errno.h>
-#include <pthread.h>
#include <stdlib.h>
+#ifdef _WIN32
+#include "lldb/Host/windows/windows.h"
+#else
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
+#endif
// C++ Includes
// Other libraries and framework includes
@@ -73,7 +76,12 @@ ConnectionSharedMemory::Disconnect (Error *error_ptr)
m_mmap.Clear();
if (!m_name.empty())
{
+#ifdef _WIN32
+ close(m_fd);
+ m_fd = -1;
+#else
shm_unlink (m_name.c_str());
+#endif
m_name.clear();
}
return eConnectionStatusSuccess;
@@ -114,6 +122,16 @@ ConnectionSharedMemory::Open (bool create, const char *name, size_t size, Error
}
m_name.assign (name);
+
+#ifdef _WIN32
+ HANDLE handle;
+ if (create)
+ handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, (DWORD)(size >> 32), (DWORD)(size), name);
+ else
+ handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name);
+
+ m_fd = _open_osfhandle((intptr_t)handle, 0);
+#else
int oflag = O_RDWR;
if (create)
oflag |= O_CREAT;
@@ -121,6 +139,7 @@ ConnectionSharedMemory::Open (bool create, const char *name, size_t size, Error
if (create)
::ftruncate (m_fd, size);
+#endif
if (m_mmap.MemoryMapFromFileDescriptor(m_fd, 0, size, true, false) == size)
return eConnectionStatusSuccess;
diff --git a/source/Core/ConstString.cpp b/source/Core/ConstString.cpp
index 875169428d2a..ce6e51108db5 100644
--- a/source/Core/ConstString.cpp
+++ b/source/Core/ConstString.cpp
@@ -259,8 +259,8 @@ int
ConstString::Compare (const ConstString& lhs, const ConstString& rhs)
{
// If the iterators are the same, this is the same string
- register const char *lhs_cstr = lhs.m_string;
- register const char *rhs_cstr = rhs.m_string;
+ const char *lhs_cstr = lhs.m_string;
+ const char *rhs_cstr = rhs.m_string;
if (lhs_cstr == rhs_cstr)
return 0;
if (lhs_cstr && rhs_cstr)
@@ -319,7 +319,7 @@ bool
ConstString::GetMangledCounterpart (ConstString &counterpart) const
{
counterpart.m_string = StringPool().GetMangledCounterpart(m_string);
- return counterpart;
+ return (bool)counterpart;
}
void
diff --git a/source/Core/DataBufferMemoryMap.cpp b/source/Core/DataBufferMemoryMap.cpp
index a4382a0c67e1..008b736ef726 100644
--- a/source/Core/DataBufferMemoryMap.cpp
+++ b/source/Core/DataBufferMemoryMap.cpp
@@ -12,7 +12,11 @@
#include <fcntl.h>
#include <limits.h>
#include <sys/stat.h>
+#ifdef _WIN32
+#include "lldb/Host/windows/windows.h"
+#else
#include <sys/mman.h>
+#endif
#include "lldb/Core/DataBufferMemoryMap.h"
#include "lldb/Core/Error.h"
@@ -86,7 +90,11 @@ 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);
+#ifdef _WIN32
+ UnmapViewOfFile(m_mmap_addr);
+#else
::munmap((void *)m_mmap_addr, m_mmap_size);
+#endif
m_mmap_addr = NULL;
m_mmap_size = 0;
m_data = NULL;
@@ -139,7 +147,17 @@ 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;
+}
+#endif
//----------------------------------------------------------------------
// The file descriptor FD is assumed to already be opened as read only
@@ -166,13 +184,59 @@ 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
fd,
offset,
length,
writeable,
fd_is_file);
}
+#ifdef _WIN32
+ 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)
+ {
+ // Cap the length if too much data was requested
+ length = max_bytes_available;
+ }
+
+ if (length > 0)
+ {
+ 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 ();
+ } else {
+ m_data = m_mmap_addr + delta;
+ m_size = length;
+ }
+ CloseHandle(fileMapping);
+ }
+ }
+#else
struct stat stat;
if (::fstat(fd, &stat) == 0)
{
@@ -253,6 +317,7 @@ DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd,
}
}
}
+#endif
}
return GetByteSize ();
}
diff --git a/source/Core/DataExtractor.cpp b/source/Core/DataExtractor.cpp
index 518faeb71ea7..d1f3c09c2305 100644
--- a/source/Core/DataExtractor.cpp
+++ b/source/Core/DataExtractor.cpp
@@ -935,6 +935,10 @@ DataExtractor::ExtractBytes (offset_t offset, offset_t length, ByteOrder dst_byt
{
if (dst_byte_order != GetByteOrder())
{
+ // Validate that only a word- or register-sized dst is byte swapped
+ assert (length == 1 || length == 2 || length == 4 || length == 8 ||
+ length == 10 || length == 16 || length == 32);
+
for (uint32_t i=0; i<length; ++i)
((uint8_t*)dst)[i] = src[length - i - 1];
}
@@ -945,6 +949,21 @@ DataExtractor::ExtractBytes (offset_t offset, offset_t length, ByteOrder dst_byt
return 0;
}
+// Extract data as it exists in target memory
+lldb::offset_t
+DataExtractor::CopyData (offset_t offset,
+ offset_t length,
+ void *dst) const
+{
+ const uint8_t *src = PeekData (offset, length);
+ if (src)
+ {
+ ::memcpy (dst, src, length);
+ return length;
+ }
+ return 0;
+}
+
// Extract data and swap if needed when doing the copy
lldb::offset_t
DataExtractor::CopyByteOrderedData (offset_t src_offset,
@@ -963,7 +982,12 @@ DataExtractor::CopyByteOrderedData (offset_t src_offset,
assert (dst_void_ptr != NULL);
assert (dst_len > 0);
assert (dst_byte_order == eByteOrderBig || dst_byte_order == eByteOrderLittle);
-
+
+ // Validate that only a word- or register-sized dst is byte swapped
+ assert (dst_byte_order == m_byte_order || dst_len == 1 || dst_len == 2 ||
+ dst_len == 4 || dst_len == 8 || dst_len == 10 || dst_len == 16 ||
+ dst_len == 32);
+
// Must have valid byte orders set in this object and for destination
if (!(dst_byte_order == eByteOrderBig || dst_byte_order == eByteOrderLittle) ||
!(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle))
@@ -1330,18 +1354,22 @@ DumpAPInt (Stream *s, const DataExtractor &data, lldb::offset_t offset, lldb::of
static float half2float (uint16_t half)
{
+#ifdef _MSC_VER
+ llvm_unreachable("half2float not implemented for MSVC");
+#else
union{ float f; uint32_t u;}u;
int32_t v = (int16_t) half;
if( 0 == (v & 0x7c00))
{
u.u = v & 0x80007FFFU;
- return u.f * 0x1.0p125f;
+ return u.f * ldexpf(1, 125);
}
v <<= 13;
u.u = v | 0x70000000U;
- return u.f * 0x1.0p-112f;
+ return u.f * ldexpf(1, -112);
+#endif
}
lldb::offset_t
@@ -1703,29 +1731,35 @@ DataExtractor::Dump (Stream *s,
case eFormatHexUppercase:
{
bool wantsuppercase = (item_format == eFormatHexUppercase);
- if (item_byte_size <= 8)
+ switch (item_byte_size)
{
+ case 1:
+ case 2:
+ case 4:
+ case 8:
s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64, (int)(2 * item_byte_size), (int)(2 * item_byte_size), GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset));
- }
- else
- {
- assert (item_bit_size == 0 && item_bit_offset == 0);
- s->PutCString("0x");
- const uint8_t *bytes = (const uint8_t* )GetData(&offset, item_byte_size);
- if (bytes)
+ break;
+ default:
{
- uint32_t idx;
- if (m_byte_order == eByteOrderBig)
- {
- for (idx = 0; idx < item_byte_size; ++idx)
- s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]);
- }
- else
+ assert (item_bit_size == 0 && item_bit_offset == 0);
+ const uint8_t *bytes = (const uint8_t* )GetData(&offset, item_byte_size);
+ if (bytes)
{
- for (idx = 0; idx < item_byte_size; ++idx)
- s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[item_byte_size - 1 - idx]);
+ s->PutCString("0x");
+ uint32_t idx;
+ if (m_byte_order == eByteOrderBig)
+ {
+ for (idx = 0; idx < item_byte_size; ++idx)
+ s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]);
+ }
+ else
+ {
+ for (idx = 0; idx < item_byte_size; ++idx)
+ s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[item_byte_size - 1 - idx]);
+ }
}
}
+ break;
}
}
break;
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
index d1d2ebb0550b..3941d82d47b0 100644
--- a/source/Core/Debugger.cpp
+++ b/source/Core/Debugger.cpp
@@ -132,6 +132,7 @@ g_properties[] =
{ "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." },
{ "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." },
{ "use-color", OptionValue::eTypeBoolean, true, true , NULL, NULL, "Whether to use Ansi color codes or not." },
+{ "auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." },
{ NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL }
};
@@ -151,6 +152,7 @@ enum
ePropertyThreadFormat,
ePropertyUseExternalEditor,
ePropertyUseColor,
+ ePropertyAutoOneLineSummaries
};
//
@@ -347,6 +349,14 @@ Debugger::GetDisassemblyLineCount () const
return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value);
}
+bool
+Debugger::GetAutoOneLineSummaries () const
+{
+ const uint32_t idx = ePropertyAutoOneLineSummaries;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);
+
+}
+
#pragma mark Debugger
//const DebuggerPropertiesSP &
@@ -821,7 +831,6 @@ Debugger::GetSelectedExecutionContext ()
}
}
return exe_ctx;
-
}
InputReaderSP
@@ -1720,7 +1729,6 @@ FormatPromptRecurse
do_deref_pointer = false;
}
- // <rdar://problem/11338654>
// 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
@@ -1902,12 +1910,12 @@ FormatPromptRecurse
if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f')
{
format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename();
- var_success = format_file_spec;
+ var_success = (bool)format_file_spec;
}
else
{
format_file_spec = exe_module->GetFileSpec();
- var_success = format_file_spec;
+ var_success = (bool)format_file_spec;
}
}
}
@@ -1983,7 +1991,7 @@ FormatPromptRecurse
ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
if (return_valobj_sp)
{
- ValueObject::DumpValueObject (s, return_valobj_sp.get());
+ return_valobj_sp->Dump(s);
var_success = true;
}
}
@@ -2067,12 +2075,12 @@ FormatPromptRecurse
if (IsToken (var_name_begin, "basename}"))
{
format_file_spec.GetFilename() = module->GetFileSpec().GetFilename();
- var_success = format_file_spec;
+ var_success = (bool)format_file_spec;
}
else if (IsToken (var_name_begin, "fullpath}"))
{
format_file_spec = module->GetFileSpec();
- var_success = format_file_spec;
+ var_success = (bool)format_file_spec;
}
}
}
@@ -2091,12 +2099,12 @@ FormatPromptRecurse
if (IsToken (var_name_begin, "basename}"))
{
format_file_spec.GetFilename() = sc->comp_unit->GetFilename();
- var_success = format_file_spec;
+ var_success = (bool)format_file_spec;
}
else if (IsToken (var_name_begin, "fullpath}"))
{
format_file_spec = *sc->comp_unit;
- var_success = format_file_spec;
+ var_success = (bool)format_file_spec;
}
}
}
@@ -2355,12 +2363,12 @@ FormatPromptRecurse
if (IsToken (var_name_begin, "basename}"))
{
format_file_spec.GetFilename() = sc->line_entry.file.GetFilename();
- var_success = format_file_spec;
+ var_success = (bool)format_file_spec;
}
else if (IsToken (var_name_begin, "fullpath}"))
{
format_file_spec = sc->line_entry.file;
- var_success = format_file_spec;
+ var_success = (bool)format_file_spec;
}
}
else if (IsTokenWithFormat (var_name_begin, "number", token_format, "%" PRIu64, exe_ctx, sc))
diff --git a/source/Core/Disassembler.cpp b/source/Core/Disassembler.cpp
index e80e92c91b51..7f830acba1f7 100644
--- a/source/Core/Disassembler.cpp
+++ b/source/Core/Disassembler.cpp
@@ -235,7 +235,8 @@ Disassembler::DisassembleRange
const char *plugin_name,
const char *flavor,
const ExecutionContext &exe_ctx,
- const AddressRange &range
+ const AddressRange &range,
+ bool prefer_file_cache
)
{
lldb::DisassemblerSP disasm_sp;
@@ -245,7 +246,6 @@ Disassembler::DisassembleRange
if (disasm_sp)
{
- const bool prefer_file_cache = false;
size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, NULL, prefer_file_cache);
if (bytes_disassembled == 0)
disasm_sp.reset();
@@ -611,8 +611,8 @@ Instruction::Dump (lldb_private::Stream *s,
}
else
{
- // Else, we have ARM which can show up to a uint32_t 0x00000000 (10 spaces)
- // plus two for padding...
+ // Else, we have ARM or MIPS which can show up to a uint32_t
+ // 0x00000000 (10 spaces) plus two for padding...
if (max_opcode_byte_size > 0)
m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1);
else
diff --git a/source/Core/Error.cpp b/source/Core/Error.cpp
index e29f12f0b2cd..7aabe5b386d4 100644
--- a/source/Core/Error.cpp
+++ b/source/Core/Error.cpp
@@ -8,7 +8,9 @@
//===----------------------------------------------------------------------===//
// C Includes
-#include <errno.h>
+#ifdef __APPLE__
+#include <mach/mach.h>
+#endif
// C++ Includes
// Other libraries and framework includes
@@ -16,9 +18,8 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "llvm/ADT/SmallVector.h"
+#include <cerrno>
#include <cstdarg>
-#include <cstdlib>
-#include <cstring>
#if defined (__arm__) && defined (__APPLE__)
#include <SpringBoardServices/SpringBoardServer.h>
@@ -51,12 +52,16 @@ Error::Error (const Error &rhs) :
{
}
-Error::Error (const char* err_str):
+Error::Error (const char* format, ...):
m_code (0),
m_type (eErrorTypeInvalid),
m_string ()
{
- SetErrorString(err_str);
+ va_list args;
+ va_start (args, format);
+ SetErrorToGenericError ();
+ SetErrorStringWithVarArg (format, args);
+ va_end (args);
}
//----------------------------------------------------------------------
@@ -238,7 +243,7 @@ Error::LogIfError (Log *log, const char *format, ...)
if (err_str == NULL)
err_str = "???";
- SetErrorStringWithFormat("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_code);
+ SetErrorStringWithFormat("%s err = %s (0x%8.8x)", arg_msg, err_str, m_code);
if (log)
log->Error("%s", m_string.c_str());
diff --git a/source/Core/FileLineResolver.cpp b/source/Core/FileLineResolver.cpp
index 15cbbe6ff9e2..b1346bbdd812 100644
--- a/source/Core/FileLineResolver.cpp
+++ b/source/Core/FileLineResolver.cpp
@@ -50,7 +50,7 @@ FileLineResolver::SearchCallback
{
CompileUnit *cu = context.comp_unit;
- if (m_inlines || m_file_spec.Compare(*cu, m_file_spec, m_file_spec.GetDirectory()))
+ if (m_inlines || m_file_spec.Compare(*cu, m_file_spec, (bool)m_file_spec.GetDirectory()))
{
uint32_t start_file_idx = 0;
uint32_t file_idx = cu->GetSupportFiles().FindFileIndex(start_file_idx, m_file_spec, false);
diff --git a/source/Core/Log.cpp b/source/Core/Log.cpp
index d73ab15f697a..8d659cfd7522 100644
--- a/source/Core/Log.cpp
+++ b/source/Core/Log.cpp
@@ -10,11 +10,9 @@
#include "lldb/lldb-python.h"
// C Includes
-#include <pthread.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
-#include <unistd.h>
// C++ Includes
#include <map>
@@ -101,8 +99,8 @@ Log::PrintfWithFlagsVarArg (uint32_t flags, const char *format, va_list args)
// Timestamp if requested
if (m_options.Test (LLDB_LOG_OPTION_PREPEND_TIMESTAMP))
{
- struct timeval tv = TimeValue::Now().GetAsTimeVal();
- header.Printf ("%9ld.%6.6d ", tv.tv_sec, (int32_t)tv.tv_usec);
+ TimeValue now = TimeValue::Now();
+ header.Printf ("%9d.%6.6d ", now.seconds(), now.nanoseconds());
}
// Add the process and thread if requested
diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp
index 4655eb131a6c..189c3bc5531d 100644
--- a/source/Core/Mangled.cpp
+++ b/source/Core/Mangled.cpp
@@ -10,7 +10,4696 @@
// FreeBSD9-STABLE requires this to know about size_t in cxxabi.h
#include <cstddef>
+#if defined(_MSC_VER) || defined (__FreeBSD__)
+#define LLDB_USE_BUILTIN_DEMANGLER
+#else
#include <cxxabi.h>
+#endif
+
+#ifdef LLDB_USE_BUILTIN_DEMANGLER
+
+#include <vector>
+#include <algorithm>
+#include <string>
+#include <numeric>
+#include <cstdlib>
+#include <cstring>
+#include <cctype>
+//----------------------------------------------------------------------
+// Inlined copy of:
+// http://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp
+// revision 193704.
+//
+// Changes include:
+// - remove the "__cxxabiv1" namespace
+// - stripped GCC attributes()
+// - removed extern "C" from the cxa_demangle function
+// - Changed the scope of the unnamed namespace to include cxa_demangle
+// function.
+//----------------------------------------------------------------------
+
+namespace
+{
+
+enum
+{
+ unknown_error = -4,
+ invalid_args = -3,
+ invalid_mangled_name,
+ memory_alloc_failure,
+ success
+};
+
+template <class C>
+ const char* parse_type(const char* first, const char* last, C& db);
+template <class C>
+ const char* parse_encoding(const char* first, const char* last, C& db);
+template <class C>
+ const char* parse_name(const char* first, const char* last, C& db);
+template <class C>
+ const char* parse_expression(const char* first, const char* last, C& db);
+template <class C>
+ const char* parse_template_args(const char* first, const char* last, C& db);
+template <class C>
+ const char* parse_operator_name(const char* first, const char* last, C& db);
+template <class C>
+ const char* parse_unqualified_name(const char* first, const char* last, C& db);
+template <class C>
+ const char* parse_decltype(const char* first, const char* last, C& db);
+
+template <class C>
+void
+print_stack(const C& db)
+{
+ printf("---------\n");
+ printf("names:\n");
+ for (auto& s : db.names)
+ printf("{%s#%s}\n", s.first.c_str(), s.second.c_str());
+ int i = -1;
+ printf("subs:\n");
+ for (auto& v : db.subs)
+ {
+ if (i >= 0)
+ printf("S%i_ = {", i);
+ else
+ printf("S_ = {");
+ for (auto& s : v)
+ printf("{%s#%s}", s.first.c_str(), s.second.c_str());
+ printf("}\n");
+ ++i;
+ }
+ printf("template_param:\n");
+ for (auto& t : db.template_param)
+ {
+ printf("--\n");
+ i = -1;
+ for (auto& v : t)
+ {
+ if (i >= 0)
+ printf("T%i_ = {", i);
+ else
+ printf("T_ = {");
+ for (auto& s : v)
+ printf("{%s#%s}", s.first.c_str(), s.second.c_str());
+ printf("}\n");
+ ++i;
+ }
+ }
+ printf("---------\n\n");
+}
+
+template <class C>
+void
+print_state(const char* msg, const char* first, const char* last, const C& db)
+{
+ printf("%s: ", msg);
+ for (; first != last; ++first)
+ printf("%c", *first);
+ printf("\n");
+ print_stack(db);
+}
+
+// <number> ::= [n] <non-negative decimal integer>
+
+const char*
+parse_number(const char* first, const char* last)
+{
+ if (first != last)
+ {
+ const char* t = first;
+ if (*t == 'n')
+ ++t;
+ if (t != last)
+ {
+ if (*t == '0')
+ {
+ first = t+1;
+ }
+ else if ('1' <= *t && *t <= '9')
+ {
+ first = t+1;
+ while (first != last && std::isdigit(*first))
+ ++first;
+ }
+ }
+ }
+ return first;
+}
+
+template <class Float>
+struct float_data;
+
+template <>
+struct float_data<float>
+{
+ static const size_t mangled_size = 8;
+ static const size_t max_demangled_size = 24;
+ static constexpr const char* spec = "%af";
+};
+
+constexpr const char* float_data<float>::spec;
+
+template <>
+struct float_data<double>
+{
+ static const size_t mangled_size = 16;
+ static const size_t max_demangled_size = 32;
+ static constexpr const char* spec = "%a";
+};
+
+constexpr const char* float_data<double>::spec;
+
+template <>
+struct float_data<long double>
+{
+ static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
+ static const size_t max_demangled_size = 40;
+ static constexpr const char* spec = "%LaL";
+};
+
+constexpr const char* float_data<long double>::spec;
+
+template <class Float, class C>
+const char*
+parse_floating_number(const char* first, const char* last, C& db)
+{
+ const size_t N = float_data<Float>::mangled_size;
+ if (static_cast<std::size_t>(last - first) > N)
+ {
+ last = first + N;
+ union
+ {
+ Float value;
+ char buf[sizeof(Float)];
+ };
+ const char* t = first;
+ char* e = buf;
+ for (; t != last; ++t, ++e)
+ {
+ if (!isxdigit(*t))
+ return first;
+ unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0') :
+ static_cast<unsigned>(*t - 'a' + 10);
+ ++t;
+ unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0') :
+ static_cast<unsigned>(*t - 'a' + 10);
+ *e = static_cast<char>((d1 << 4) + d0);
+ }
+ if (*t == 'E')
+ {
+#if __LITTLE_ENDIAN__
+ std::reverse(buf, e);
+#endif
+ char num[float_data<Float>::max_demangled_size] = {0};
+ int n = snprintf(num, sizeof(num), float_data<Float>::spec, value);
+ if (static_cast<std::size_t>(n) >= sizeof(num))
+ return first;
+ db.names.push_back(typename C::String(num, static_cast<std::size_t>(n)));
+ first = t+1;
+ }
+ }
+ return first;
+}
+
+// <source-name> ::= <positive length number> <identifier>
+
+template <class C>
+const char*
+parse_source_name(const char* first, const char* last, C& db)
+{
+ if (first != last)
+ {
+ char c = *first;
+ if (isdigit(c) && first+1 != last)
+ {
+ const char* t = first+1;
+ size_t n = static_cast<size_t>(c - '0');
+ for (c = *t; isdigit(c); c = *t)
+ {
+ n = n * 10 + static_cast<size_t>(c - '0');
+ if (++t == last)
+ return first;
+ }
+ if (static_cast<size_t>(last - t) >= n)
+ {
+ typename C::String r(t, n);
+ if (r.substr(0, 10) == "_GLOBAL__N")
+ db.names.push_back("(anonymous namespace)");
+ else
+ db.names.push_back(std::move(r));
+ first = t + n;
+ }
+ }
+ }
+ return first;
+}
+
+// <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> >
+
+template <class C>
+const char*
+parse_substitution(const char* first, const char* last, C& db)
+{
+ if (last - first >= 2)
+ {
+ if (*first == 'S')
+ {
+ switch (first[1])
+ {
+ case 'a':
+ db.names.push_back("std::allocator");
+ first += 2;
+ break;
+ case 'b':
+ db.names.push_back("std::basic_string");
+ first += 2;
+ break;
+ case 's':
+ db.names.push_back("std::string");
+ first += 2;
+ break;
+ case 'i':
+ db.names.push_back("std::istream");
+ first += 2;
+ break;
+ case 'o':
+ db.names.push_back("std::ostream");
+ first += 2;
+ break;
+ case 'd':
+ db.names.push_back("std::iostream");
+ first += 2;
+ break;
+ case '_':
+ if (!db.subs.empty())
+ {
+ for (const auto& n : db.subs.front())
+ db.names.push_back(n);
+ first += 2;
+ }
+ break;
+ default:
+ if (std::isdigit(first[1]) || std::isupper(first[1]))
+ {
+ size_t sub = 0;
+ const char* t = first+1;
+ if (std::isdigit(*t))
+ sub = static_cast<size_t>(*t - '0');
+ else
+ sub = static_cast<size_t>(*t - 'A') + 10;
+ for (++t; t != last && (std::isdigit(*t) || std::isupper(*t)); ++t)
+ {
+ sub *= 36;
+ if (std::isdigit(*t))
+ sub += static_cast<size_t>(*t - '0');
+ else
+ sub += static_cast<size_t>(*t - 'A') + 10;
+ }
+ if (t == last || *t != '_')
+ return first;
+ ++sub;
+ if (sub < db.subs.size())
+ {
+ for (const auto& n : db.subs[sub])
+ db.names.push_back(n);
+ first = t+1;
+ }
+ }
+ break;
+ }
+ }
+ }
+ return first;
+}
+
+// <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
+
+template <class C>
+const char*
+parse_builtin_type(const char* first, const char* last, C& db)
+{
+ if (first != last)
+ {
+ switch (*first)
+ {
+ case 'v':
+ db.names.push_back("void");
+ ++first;
+ break;
+ case 'w':
+ db.names.push_back("wchar_t");
+ ++first;
+ break;
+ case 'b':
+ db.names.push_back("bool");
+ ++first;
+ break;
+ case 'c':
+ db.names.push_back("char");
+ ++first;
+ break;
+ case 'a':
+ db.names.push_back("signed char");
+ ++first;
+ break;
+ case 'h':
+ db.names.push_back("unsigned char");
+ ++first;
+ break;
+ case 's':
+ db.names.push_back("short");
+ ++first;
+ break;
+ case 't':
+ db.names.push_back("unsigned short");
+ ++first;
+ break;
+ case 'i':
+ db.names.push_back("int");
+ ++first;
+ break;
+ case 'j':
+ db.names.push_back("unsigned int");
+ ++first;
+ break;
+ case 'l':
+ db.names.push_back("long");
+ ++first;
+ break;
+ case 'm':
+ db.names.push_back("unsigned long");
+ ++first;
+ break;
+ case 'x':
+ db.names.push_back("long long");
+ ++first;
+ break;
+ case 'y':
+ db.names.push_back("unsigned long long");
+ ++first;
+ break;
+ case 'n':
+ db.names.push_back("__int128");
+ ++first;
+ break;
+ case 'o':
+ db.names.push_back("unsigned __int128");
+ ++first;
+ break;
+ case 'f':
+ db.names.push_back("float");
+ ++first;
+ break;
+ case 'd':
+ db.names.push_back("double");
+ ++first;
+ break;
+ case 'e':
+ db.names.push_back("long double");
+ ++first;
+ break;
+ case 'g':
+ db.names.push_back("__float128");
+ ++first;
+ break;
+ case 'z':
+ db.names.push_back("...");
+ ++first;
+ break;
+ case 'u':
+ {
+ const char*t = parse_source_name(first+1, last, db);
+ if (t != first+1)
+ first = t;
+ }
+ break;
+ case 'D':
+ if (first+1 != last)
+ {
+ switch (first[1])
+ {
+ case 'd':
+ db.names.push_back("decimal64");
+ first += 2;
+ break;
+ case 'e':
+ db.names.push_back("decimal128");
+ first += 2;
+ break;
+ case 'f':
+ db.names.push_back("decimal32");
+ first += 2;
+ break;
+ case 'h':
+ db.names.push_back("decimal16");
+ first += 2;
+ break;
+ case 'i':
+ db.names.push_back("char32_t");
+ first += 2;
+ break;
+ case 's':
+ db.names.push_back("char16_t");
+ first += 2;
+ break;
+ case 'a':
+ db.names.push_back("auto");
+ first += 2;
+ break;
+ case 'n':
+ db.names.push_back("std::nullptr_t");
+ first += 2;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ return first;
+}
+
+// <CV-qualifiers> ::= [r] [V] [K]
+
+const char*
+parse_cv_qualifiers(const char* first, const char* last, unsigned& cv)
+{
+ cv = 0;
+ if (first != last)
+ {
+ if (*first == 'r')
+ {
+ cv |= 4;
+ ++first;
+ }
+ if (*first == 'V')
+ {
+ cv |= 2;
+ ++first;
+ }
+ if (*first == 'K')
+ {
+ cv |= 1;
+ ++first;
+ }
+ }
+ return first;
+}
+
+// <template-param> ::= T_ # first template parameter
+// ::= T <parameter-2 non-negative number> _
+
+template <class C>
+const char*
+parse_template_param(const char* first, const char* last, C& db)
+{
+ if (last - first >= 2)
+ {
+ if (*first == 'T')
+ {
+ if (first[1] == '_')
+ {
+ if (!db.template_param.back().empty())
+ {
+ for (auto& t : db.template_param.back().front())
+ db.names.push_back(t);
+ first += 2;
+ }
+ else
+ {
+ db.names.push_back("T_");
+ first += 2;
+ db.fix_forward_references = true;
+ }
+ }
+ else if (isdigit(first[1]))
+ {
+ const char* t = first+1;
+ size_t sub = static_cast<size_t>(*t - '0');
+ for (++t; t != last && isdigit(*t); ++t)
+ {
+ sub *= 10;
+ sub += static_cast<size_t>(*t - '0');
+ }
+ if (t == last || *t != '_')
+ return first;
+ ++sub;
+ if (sub < db.template_param.back().size())
+ {
+ for (auto& temp : db.template_param.back()[sub])
+ db.names.push_back(temp);
+ first = t+1;
+ }
+ else
+ {
+ db.names.push_back(typename C::String(first, t+1));
+ first = t+1;
+ db.fix_forward_references = true;
+ }
+ }
+ }
+ }
+ return first;
+}
+
+// cc <type> <expression> # const_cast<type> (expression)
+
+template <class C>
+const char*
+parse_const_cast_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 'c' && first[1] == 'c')
+ {
+ const char* t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ const char* t1 = parse_expression(t, last, db);
+ if (t1 != t)
+ {
+ auto expr = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back() = "const_cast<" + db.names.back().move_full() + ">(" + expr + ")";
+ first = t1;
+ }
+ }
+ }
+ return first;
+}
+
+// dc <type> <expression> # dynamic_cast<type> (expression)
+
+template <class C>
+const char*
+parse_dynamic_cast_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 'd' && first[1] == 'c')
+ {
+ const char* t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ const char* t1 = parse_expression(t, last, db);
+ if (t1 != t)
+ {
+ auto expr = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back() = "dynamic_cast<" + db.names.back().move_full() + ">(" + expr + ")";
+ first = t1;
+ }
+ }
+ }
+ return first;
+}
+
+// rc <type> <expression> # reinterpret_cast<type> (expression)
+
+template <class C>
+const char*
+parse_reinterpret_cast_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 'r' && first[1] == 'c')
+ {
+ const char* t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ const char* t1 = parse_expression(t, last, db);
+ if (t1 != t)
+ {
+ auto expr = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back() = "reinterpret_cast<" + db.names.back().move_full() + ">(" + expr + ")";
+ first = t1;
+ }
+ }
+ }
+ return first;
+}
+
+// sc <type> <expression> # static_cast<type> (expression)
+
+template <class C>
+const char*
+parse_static_cast_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 's' && first[1] == 'c')
+ {
+ const char* t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ const char* t1 = parse_expression(t, last, db);
+ if (t1 != t)
+ {
+ auto expr = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back() = "static_cast<" + db.names.back().move_full() + ">(" + expr + ")";
+ first = t1;
+ }
+ }
+ }
+ return first;
+}
+
+// sp <expression> # pack expansion
+
+template <class C>
+const char*
+parse_pack_expansion(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 's' && first[1] == 'p')
+ {
+ const char* t = parse_expression(first+2, last, db);
+ if (t != first+2)
+ first = t;
+ }
+ return first;
+}
+
+// st <type> # sizeof (a type)
+
+template <class C>
+const char*
+parse_sizeof_type_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 's' && first[1] == 't')
+ {
+ const char* t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back() = "sizeof (" + db.names.back().move_full() + ")";
+ first = t;
+ }
+ }
+ return first;
+}
+
+// sz <expr> # sizeof (a expression)
+
+template <class C>
+const char*
+parse_sizeof_expr_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 's' && first[1] == 'z')
+ {
+ const char* t = parse_expression(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back() = "sizeof (" + db.names.back().move_full() + ")";
+ first = t;
+ }
+ }
+ return first;
+}
+
+// sZ <template-param> # size of a parameter pack
+
+template <class C>
+const char*
+parse_sizeof_param_pack_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && first[2] == 'T')
+ {
+ size_t k0 = db.names.size();
+ const char* t = parse_template_param(first+2, last, db);
+ size_t k1 = db.names.size();
+ if (t != first+2)
+ {
+ typename C::String tmp("sizeof...(");
+ size_t k = k0;
+ if (k != k1)
+ {
+ tmp += db.names[k].move_full();
+ for (++k; k != k1; ++k)
+ tmp += ", " + db.names[k].move_full();
+ }
+ tmp += ")";
+ for (; k1 != k0; --k1)
+ db.names.pop_back();
+ db.names.push_back(std::move(tmp));
+ first = t;
+ }
+ }
+ return first;
+}
+
+// <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter
+// ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
+// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _ # L > 0, first parameter
+// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
+
+template <class C>
+const char*
+parse_function_param(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && *first == 'f')
+ {
+ if (first[1] == 'p')
+ {
+ unsigned cv;
+ const char* t = parse_cv_qualifiers(first+2, last, cv);
+ const char* t1 = parse_number(t, last);
+ if (t1 != last && *t1 == '_')
+ {
+ db.names.push_back("fp" + typename C::String(t, t1));
+ first = t1+1;
+ }
+ }
+ else if (first[1] == 'L')
+ {
+ unsigned cv;
+ const char* t0 = parse_number(first+2, last);
+ if (t0 != last && *t0 == 'p')
+ {
+ ++t0;
+ const char* t = parse_cv_qualifiers(t0, last, cv);
+ const char* t1 = parse_number(t, last);
+ if (t1 != last && *t1 == '_')
+ {
+ db.names.push_back("fp" + typename C::String(t, t1));
+ first = t1+1;
+ }
+ }
+ }
+ }
+ return first;
+}
+
+// sZ <function-param> # size of a function parameter pack
+
+template <class C>
+const char*
+parse_sizeof_function_param_pack_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && first[2] == 'f')
+ {
+ const char* t = parse_function_param(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back() = "sizeof...(" + db.names.back().move_full() + ")";
+ first = t;
+ }
+ }
+ return first;
+}
+
+// te <expression> # typeid (expression)
+// ti <type> # typeid (type)
+
+template <class C>
+const char*
+parse_typeid_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 't' && (first[1] == 'e' || first[1] == 'i'))
+ {
+ const char* t;
+ if (first[1] == 'e')
+ t = parse_expression(first+2, last, db);
+ else
+ t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back() = "typeid(" + db.names.back().move_full() + ")";
+ first = t;
+ }
+ }
+ return first;
+}
+
+// tw <expression> # throw expression
+
+template <class C>
+const char*
+parse_throw_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 't' && first[1] == 'w')
+ {
+ const char* t = parse_expression(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back() = "throw " + db.names.back().move_full();
+ first = t;
+ }
+ }
+ return first;
+}
+
+// ds <expression> <expression> # expr.*expr
+
+template <class C>
+const char*
+parse_dot_star_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 'd' && first[1] == 's')
+ {
+ const char* t = parse_expression(first+2, last, db);
+ if (t != first+2)
+ {
+ const char* t1 = parse_expression(t, last, db);
+ if (t1 != t)
+ {
+ auto expr = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += ".*" + expr;
+ first = t1;
+ }
+ }
+ }
+ return first;
+}
+
+// <simple-id> ::= <source-name> [ <template-args> ]
+
+template <class C>
+const char*
+parse_simple_id(const char* first, const char* last, C& db)
+{
+ if (first != last)
+ {
+ const char* t = parse_source_name(first, last, db);
+ if (t != first)
+ {
+ const char* t1 = parse_template_args(t, last, db);
+ if (t1 != t)
+ {
+ auto args = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += std::move(args);
+ }
+ first = t1;
+ }
+ else
+ first = t;
+ }
+ return first;
+}
+
+// <unresolved-type> ::= <template-param>
+// ::= <decltype>
+// ::= <substitution>
+
+template <class C>
+const char*
+parse_unresolved_type(const char* first, const char* last, C& db)
+{
+ if (first != last)
+ {
+ const char* t = first;
+ switch (*first)
+ {
+ case 'T':
+ {
+ size_t k0 = db.names.size();
+ t = parse_template_param(first, last, db);
+ size_t k1 = db.names.size();
+ if (t != first && k1 == k0 + 1)
+ {
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ first = t;
+ }
+ else
+ {
+ for (; k1 != k0; --k1)
+ db.names.pop_back();
+ }
+ break;
+ }
+ case 'D':
+ t = parse_decltype(first, last, db);
+ if (t != first)
+ {
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ first = t;
+ }
+ break;
+ case 'S':
+ t = parse_substitution(first, last, db);
+ if (t != first)
+ first = t;
+ else
+ {
+ if (last - first > 2 && first[1] == 't')
+ {
+ t = parse_unqualified_name(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back().first.insert(0, "std::");
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ first = t;
+ }
+ }
+ }
+ break;
+ }
+ }
+ return first;
+}
+
+// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
+// ::= <simple-id> # e.g., ~A<2*N>
+
+template <class C>
+const char*
+parse_destructor_name(const char* first, const char* last, C& db)
+{
+ if (first != last)
+ {
+ const char* t = parse_unresolved_type(first, last, db);
+ if (t == first)
+ t = parse_simple_id(first, last, db);
+ if (t != first)
+ {
+ db.names.back().first.insert(0, "~");
+ first = t;
+ }
+ }
+ return first;
+}
+
+// <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>
+
+template <class C>
+const char*
+parse_base_unresolved_name(const char* first, const char* last, C& db)
+{
+ if (last - first >= 2)
+ {
+ if ((first[0] == 'o' || first[0] == 'd') && first[1] == 'n')
+ {
+ if (first[0] == 'o')
+ {
+ const char* t = parse_operator_name(first+2, last, db);
+ if (t != first+2)
+ {
+ first = parse_template_args(t, last, db);
+ if (first != t)
+ {
+ auto args = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += std::move(args);
+ }
+ }
+ }
+ else
+ {
+ const char* t = parse_destructor_name(first+2, last, db);
+ if (t != first+2)
+ first = t;
+ }
+ }
+ else
+ {
+ const char* t = parse_simple_id(first, last, db);
+ if (t == first)
+ {
+ t = parse_operator_name(first, last, db);
+ if (t != first)
+ {
+ first = parse_template_args(t, last, db);
+ if (first != t)
+ {
+ auto args = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += std::move(args);
+ }
+ }
+ }
+ else
+ first = t;
+ }
+ }
+ return first;
+}
+
+// <unresolved-qualifier-level> ::= <simple-id>
+
+template <class C>
+const char*
+parse_unresolved_qualifier_level(const char* first, const char* last, C& db)
+{
+ return parse_simple_id(first, last, db);
+}
+
+// <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>
+
+template <class C>
+const char*
+parse_unresolved_name(const char* first, const char* last, C& db)
+{
+ if (last - first > 2)
+ {
+ const char* t = first;
+ bool global = false;
+ if (t[0] == 'g' && t[1] == 's')
+ {
+ global = true;
+ t += 2;
+ }
+ const char* t2 = parse_base_unresolved_name(t, last, db);
+ if (t2 != t)
+ {
+ if (global)
+ db.names.back().first.insert(0, "::");
+ first = t2;
+ }
+ else if (last - t > 2 && t[0] == 's' && t[1] == 'r')
+ {
+ if (t[2] == 'N')
+ {
+ t += 3;
+ const char* t1 = parse_unresolved_type(t, last, db);
+ if (t1 == t || t1 == last)
+ return first;
+ t = t1;
+ t1 = parse_template_args(t, last, db);
+ if (t1 != t)
+ {
+ auto args = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += std::move(args);
+ t = t1;
+ if (t == last)
+ {
+ db.names.pop_back();
+ return first;
+ }
+ }
+ while (*t != 'E')
+ {
+ t1 = parse_unresolved_qualifier_level(t, last, db);
+ if (t1 == t || t1 == last)
+ return first;
+ auto s = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += "::" + std::move(s);
+ t = t1;
+ }
+ ++t;
+ t1 = parse_base_unresolved_name(t, last, db);
+ if (t1 == t)
+ {
+ db.names.pop_back();
+ return first;
+ }
+ auto s = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += "::" + std::move(s);
+ first = t1;
+ }
+ else
+ {
+ t += 2;
+ const char* t1 = parse_unresolved_type(t, last, db);
+ if (t1 != t)
+ {
+ t = t1;
+ t1 = parse_template_args(t, last, db);
+ if (t1 != t)
+ {
+ auto args = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += std::move(args);
+ t = t1;
+ }
+ t1 = parse_base_unresolved_name(t, last, db);
+ if (t1 == t)
+ {
+ db.names.pop_back();
+ return first;
+ }
+ auto s = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += "::" + std::move(s);
+ first = t1;
+ }
+ else
+ {
+ t1 = parse_unresolved_qualifier_level(t, last, db);
+ if (t1 == t || t1 == last)
+ return first;
+ t = t1;
+ if (global)
+ db.names.back().first.insert(0, "::");
+ while (*t != 'E')
+ {
+ t1 = parse_unresolved_qualifier_level(t, last, db);
+ if (t1 == t || t1 == last)
+ return first;
+ auto s = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += "::" + std::move(s);
+ t = t1;
+ }
+ ++t;
+ t1 = parse_base_unresolved_name(t, last, db);
+ if (t1 == t)
+ {
+ db.names.pop_back();
+ return first;
+ }
+ auto s = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += "::" + std::move(s);
+ first = t1;
+ }
+ }
+ }
+ }
+ return first;
+}
+
+// dt <expression> <unresolved-name> # expr.name
+
+template <class C>
+const char*
+parse_dot_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 'd' && first[1] == 't')
+ {
+ const char* t = parse_expression(first+2, last, db);
+ if (t != first+2)
+ {
+ const char* t1 = parse_unresolved_name(t, last, db);
+ if (t1 != t)
+ {
+ auto name = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += "." + name;
+ first = t1;
+ }
+ }
+ }
+ return first;
+}
+
+// cl <expression>+ E # call
+
+template <class C>
+const char*
+parse_call_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 4 && first[0] == 'c' && first[1] == 'l')
+ {
+ const char* t = parse_expression(first+2, last, db);
+ if (t != first+2)
+ {
+ if (t == last)
+ return first;
+ db.names.back().first += db.names.back().second;
+ db.names.back().second = typename C::String();
+ db.names.back().first.append("(");
+ bool first_expr = true;
+ while (*t != 'E')
+ {
+ const char* t1 = parse_expression(t, last, db);
+ if (t1 == t || t1 == last)
+ return first;
+ auto tmp = db.names.back().move_full();
+ db.names.pop_back();
+ if (!tmp.empty())
+ {
+ if (!first_expr)
+ {
+ db.names.back().first.append(", ");
+ first_expr = false;
+ }
+ db.names.back().first.append(tmp);
+ }
+ t = t1;
+ }
+ ++t;
+ db.names.back().first.append(")");
+ first = t;
+ }
+ }
+ return first;
+}
+
+// [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)
+// <initializer> ::= pi <expression>* E # parenthesized initialization
+
+template <class C>
+const char*
+parse_new_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 4)
+ {
+ const char* t = first;
+ bool parsed_gs = false;
+ if (t[0] == 'g' && t[1] == 's')
+ {
+ t += 2;
+ parsed_gs = true;
+ }
+ if (t[0] == 'n' && (t[1] == 'w' || t[1] == 'a'))
+ {
+ bool is_array = t[1] == 'a';
+ t += 2;
+ if (t == last)
+ return first;
+ bool has_expr_list = false;
+ bool first_expr = true;
+ while (*t != '_')
+ {
+ const char* t1 = parse_expression(t, last, db);
+ if (t1 == t || t1 == last)
+ return first;
+ has_expr_list = true;
+ if (!first_expr)
+ {
+ auto tmp = db.names.back().move_full();
+ db.names.pop_back();
+ if (!tmp.empty())
+ {
+ db.names.back().first.append(", ");
+ db.names.back().first.append(tmp);
+ first_expr = false;
+ }
+ }
+ t = t1;
+ }
+ ++t;
+ const char* t1 = parse_type(t, last, db);
+ if (t1 == t || t1 == last)
+ return first;
+ t = t1;
+ bool has_init = false;
+ if (last - t >= 3 && t[0] == 'p' && t[1] == 'i')
+ {
+ t += 2;
+ has_init = true;
+ first_expr = true;
+ while (*t != 'E')
+ {
+ t1 = parse_expression(t, last, db);
+ if (t1 == t || t1 == last)
+ return first;
+ if (!first_expr)
+ {
+ auto tmp = db.names.back().move_full();
+ db.names.pop_back();
+ if (!tmp.empty())
+ {
+ db.names.back().first.append(", ");
+ db.names.back().first.append(tmp);
+ first_expr = false;
+ }
+ }
+ t = t1;
+ }
+ }
+ if (*t != 'E')
+ return first;
+ typename C::String init_list;
+ if (has_init)
+ {
+ init_list = db.names.back().move_full();
+ db.names.pop_back();
+ }
+ auto type = db.names.back().move_full();
+ db.names.pop_back();
+ typename C::String expr_list;
+ if (has_expr_list)
+ {
+ expr_list = db.names.back().move_full();
+ db.names.pop_back();
+ }
+ typename C::String r;
+ if (parsed_gs)
+ r = "::";
+ if (is_array)
+ r += "[] ";
+ else
+ r += " ";
+ if (has_expr_list)
+ r += "(" + expr_list + ") ";
+ r += type;
+ if (has_init)
+ r += " (" + init_list + ")";
+ db.names.push_back(std::move(r));
+ first = t+1;
+ }
+ }
+ return first;
+}
+
+// cv <type> <expression> # conversion with one argument
+// cv <type> _ <expression>* E # conversion with a different number of arguments
+
+template <class C>
+const char*
+parse_conversion_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 'c' && first[1] == 'v')
+ {
+ bool try_to_parse_template_args = db.try_to_parse_template_args;
+ db.try_to_parse_template_args = false;
+ const char* t = parse_type(first+2, last, db);
+ db.try_to_parse_template_args = try_to_parse_template_args;
+ if (t != first+2 && t != last)
+ {
+ if (*t != '_')
+ {
+ const char* t1 = parse_expression(t, last, db);
+ if (t1 == t)
+ return first;
+ t = t1;
+ }
+ else
+ {
+ ++t;
+ if (t == last)
+ return first;
+ if (*t == 'E')
+ db.names.emplace_back();
+ else
+ {
+ bool first_expr = true;
+ while (*t != 'E')
+ {
+ const char* t1 = parse_expression(t, last, db);
+ if (t1 == t || t1 == last)
+ return first;
+ if (!first_expr)
+ {
+ auto tmp = db.names.back().move_full();
+ db.names.pop_back();
+ if (!tmp.empty())
+ {
+ db.names.back().first.append(", ");
+ db.names.back().first.append(tmp);
+ first_expr = false;
+ }
+ }
+ t = t1;
+ }
+ }
+ ++t;
+ }
+ auto tmp = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back() = "(" + db.names.back().move_full() + ")(" + tmp + ")";
+ first = t;
+ }
+ }
+ return first;
+}
+
+// pt <expression> <expression> # expr->name
+
+template <class C>
+const char*
+parse_arrow_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 'p' && first[1] == 't')
+ {
+ const char* t = parse_expression(first+2, last, db);
+ if (t != first+2)
+ {
+ const char* t1 = parse_expression(t, last, db);
+ if (t1 != t)
+ {
+ auto tmp = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += "->";
+ db.names.back().first += tmp;
+ first = t1;
+ }
+ }
+ }
+ return first;
+}
+
+// <ref-qualifier> ::= R # & ref-qualifier
+// <ref-qualifier> ::= O # && ref-qualifier
+
+// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
+
+template <class C>
+const char*
+parse_function_type(const char* first, const char* last, C& db)
+{
+ if (first != last && *first == 'F')
+ {
+ const char* t = first+1;
+ if (t != last)
+ {
+ bool externC = false;
+ if (*t == 'Y')
+ {
+ externC = true;
+ if (++t == last)
+ return first;
+ }
+ const char* t1 = parse_type(t, last, db);
+ if (t1 != t)
+ {
+ t = t1;
+ typename C::String sig("(");
+ int ref_qual = 0;
+ while (true)
+ {
+ if (t == last)
+ {
+ db.names.pop_back();
+ return first;
+ }
+ if (*t == 'E')
+ {
+ ++t;
+ break;
+ }
+ if (*t == 'v')
+ {
+ ++t;
+ continue;
+ }
+ if (*t == 'R' && t+1 != last && t[1] == 'E')
+ {
+ ref_qual = 1;
+ ++t;
+ continue;
+ }
+ if (*t == 'O' && t+1 != last && t[1] == 'E')
+ {
+ ref_qual = 2;
+ ++t;
+ continue;
+ }
+ size_t k0 = db.names.size();
+ t1 = parse_type(t, last, db);
+ size_t k1 = db.names.size();
+ if (t1 == t || t1 == last)
+ return first;
+ for (size_t k = k0; k < k1; ++k)
+ {
+ if (sig.size() > 1)
+ sig += ", ";
+ sig += db.names[k].move_full();
+ }
+ for (size_t k = k0; k < k1; ++k)
+ db.names.pop_back();
+ t = t1;
+ }
+ sig += ")";
+ switch (ref_qual)
+ {
+ case 1:
+ sig += " &";
+ break;
+ case 2:
+ sig += " &&";
+ break;
+ }
+ db.names.back().first += " ";
+ db.names.back().second.insert(0, sig);
+ first = t;
+ }
+ }
+ }
+ return first;
+}
+
+// <pointer-to-member-type> ::= M <class type> <member type>
+
+template <class C>
+const char*
+parse_pointer_to_member_type(const char* first, const char* last, C& db)
+{
+ if (first != last && *first == 'M')
+ {
+ const char* t = parse_type(first+1, last, db);
+ if (t != first+1)
+ {
+ const char* t2 = parse_type(t, last, db);
+ if (t2 != t)
+ {
+ auto func = std::move(db.names.back());
+ db.names.pop_back();
+ auto class_type = std::move(db.names.back());
+ if (func.second.front() == '(')
+ {
+ db.names.back().first = std::move(func.first) + "(" + class_type.move_full() + "::*";
+ db.names.back().second = ")" + std::move(func.second);
+ }
+ else
+ {
+ db.names.back().first = std::move(func.first) + " " + class_type.move_full() + "::*";
+ db.names.back().second = std::move(func.second);
+ }
+ first = t2;
+ }
+ }
+ }
+ return first;
+}
+
+// <array-type> ::= A <positive dimension number> _ <element type>
+// ::= A [<dimension expression>] _ <element type>
+
+template <class C>
+const char*
+parse_array_type(const char* first, const char* last, C& db)
+{
+ if (first != last && *first == 'A' && first+1 != last)
+ {
+ if (first[1] == '_')
+ {
+ const char* t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ if (db.names.back().second.substr(0, 2) == " [")
+ db.names.back().second.erase(0, 1);
+ db.names.back().second.insert(0, " []");
+ first = t;
+ }
+ }
+ else if ('1' <= first[1] && first[1] <= '9')
+ {
+ const char* t = parse_number(first+1, last);
+ if (t != last && *t == '_')
+ {
+ const char* t2 = parse_type(t+1, last, db);
+ if (t2 != t+1)
+ {
+ if (db.names.back().second.substr(0, 2) == " [")
+ db.names.back().second.erase(0, 1);
+ db.names.back().second.insert(0, " [" + typename C::String(first+1, t) + "]");
+ first = t2;
+ }
+ }
+ }
+ else
+ {
+ const char* t = parse_expression(first+1, last, db);
+ if (t != first+1 && t != last && *t == '_')
+ {
+ const char* t2 = parse_type(++t, last, db);
+ if (t2 != t)
+ {
+ auto type = std::move(db.names.back());
+ db.names.pop_back();
+ auto expr = std::move(db.names.back());
+ db.names.back().first = std::move(type.first);
+ if (type.second.substr(0, 2) == " [")
+ type.second.erase(0, 1);
+ db.names.back().second = " [" + expr.move_full() + "]" + std::move(type.second);
+ first = t2;
+ }
+ }
+ }
+ }
+ return first;
+}
+
+// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
+// ::= DT <expression> E # decltype of an expression (C++0x)
+
+template <class C>
+const char*
+parse_decltype(const char* first, const char* last, C& db)
+{
+ if (last - first >= 4 && first[0] == 'D')
+ {
+ switch (first[1])
+ {
+ case 't':
+ case 'T':
+ {
+ const char* t = parse_expression(first+2, last, db);
+ if (t != first+2 && t != last && *t == 'E')
+ {
+ db.names.back() = "decltype(" + db.names.back().move_full() + ")";
+ first = t+1;
+ }
+ }
+ break;
+ }
+ }
+ return first;
+}
+
+// extension:
+// <vector-type> ::= Dv <positive dimension number> _
+// <extended element type>
+// ::= Dv [<dimension expression>] _ <element type>
+// <extended element type> ::= <element type>
+// ::= p # AltiVec vector pixel
+
+template <class C>
+const char*
+parse_vector_type(const char* first, const char* last, C& db)
+{
+ if (last - first > 3 && first[0] == 'D' && first[1] == 'v')
+ {
+ if ('1' <= first[2] && first[2] <= '9')
+ {
+ const char* t = parse_number(first+2, last);
+ if (t == last || *t != '_')
+ return first;
+ const char* num = first + 2;
+ size_t sz = static_cast<size_t>(t - num);
+ if (++t != last)
+ {
+ if (*t != 'p')
+ {
+ const char* t1 = parse_type(t, last, db);
+ if (t1 != t)
+ {
+ db.names.back().first += " vector[" + typename C::String(num, sz) + "]";
+ first = t1;
+ }
+ }
+ else
+ {
+ ++t;
+ db.names.push_back("pixel vector[" + typename C::String(num, sz) + "]");
+ first = t;
+ }
+ }
+ }
+ else
+ {
+ typename C::String num;
+ const char* t1 = first+2;
+ if (*t1 != '_')
+ {
+ const char* t = parse_expression(t1, last, db);
+ if (t != t1)
+ {
+ num = db.names.back().move_full();
+ db.names.pop_back();
+ t1 = t;
+ }
+ }
+ if (t1 != last && *t1 == '_' && ++t1 != last)
+ {
+ const char* t = parse_type(t1, last, db);
+ if (t != t1)
+ {
+ db.names.back().first += " vector[" + num + "]";
+ first = t;
+ }
+ }
+ }
+ }
+ return first;
+}
+
+// <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>
+
+template <class C>
+const char*
+parse_type(const char* first, const char* last, C& db)
+{
+ if (first != last)
+ {
+ switch (*first)
+ {
+ case 'r':
+ case 'V':
+ case 'K':
+ {
+ unsigned cv = 0;
+ const char* t = parse_cv_qualifiers(first, last, cv);
+ if (t != first)
+ {
+ bool is_function = *t == 'F';
+ size_t k0 = db.names.size();
+ const char* t1 = parse_type(t, last, db);
+ size_t k1 = db.names.size();
+ if (t1 != t)
+ {
+ if (is_function)
+ db.subs.pop_back();
+ db.subs.emplace_back(db.names.get_allocator());
+ for (size_t k = k0; k < k1; ++k)
+ {
+ if (is_function)
+ {
+ size_t p = db.names[k].second.size();
+ if (db.names[k].second[p-2] == '&')
+ p -= 3;
+ else if (db.names[k].second.back() == '&')
+ p -= 2;
+ if (cv & 1)
+ {
+ db.names[k].second.insert(p, " const");
+ p += 6;
+ }
+ if (cv & 2)
+ {
+ db.names[k].second.insert(p, " volatile");
+ p += 9;
+ }
+ if (cv & 4)
+ db.names[k].second.insert(p, " restrict");
+ }
+ else
+ {
+ if (cv & 1)
+ db.names[k].first.append(" const");
+ if (cv & 2)
+ db.names[k].first.append(" volatile");
+ if (cv & 4)
+ db.names[k].first.append(" restrict");
+ }
+ db.subs.back().push_back(db.names[k]);
+ }
+ first = t1;
+ }
+ }
+ }
+ break;
+ default:
+ {
+ const char* t = parse_builtin_type(first, last, db);
+ if (t != first)
+ {
+ first = t;
+ }
+ else
+ {
+ switch (*first)
+ {
+ case 'A':
+ t = parse_array_type(first, last, db);
+ if (t != first)
+ {
+ first = t;
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ }
+ break;
+ case 'C':
+ t = parse_type(first+1, last, db);
+ if (t != first+1)
+ {
+ db.names.back().first.append(" complex");
+ first = t;
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ }
+ break;
+ case 'F':
+ t = parse_function_type(first, last, db);
+ if (t != first)
+ {
+ first = t;
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ }
+ break;
+ case 'G':
+ t = parse_type(first+1, last, db);
+ if (t != first+1)
+ {
+ db.names.back().first.append(" imaginary");
+ first = t;
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ }
+ break;
+ case 'M':
+ t = parse_pointer_to_member_type(first, last, db);
+ if (t != first)
+ {
+ first = t;
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ }
+ break;
+ case 'O':
+ {
+ size_t k0 = db.names.size();
+ t = parse_type(first+1, last, db);
+ size_t k1 = db.names.size();
+ if (t != first+1)
+ {
+ db.subs.emplace_back(db.names.get_allocator());
+ for (size_t k = k0; k < k1; ++k)
+ {
+ if (db.names[k].second.substr(0, 2) == " [")
+ {
+ db.names[k].first += " (";
+ db.names[k].second.insert(0, ")");
+ }
+ else if (db.names[k].second.front() == '(')
+ {
+ db.names[k].first += "(";
+ db.names[k].second.insert(0, ")");
+ }
+ db.names[k].first.append("&&");
+ db.subs.back().push_back(db.names[k]);
+ }
+ first = t;
+ }
+ break;
+ }
+ case 'P':
+ {
+ size_t k0 = db.names.size();
+ t = parse_type(first+1, last, db);
+ size_t k1 = db.names.size();
+ if (t != first+1)
+ {
+ db.subs.emplace_back(db.names.get_allocator());
+ for (size_t k = k0; k < k1; ++k)
+ {
+ if (db.names[k].second.substr(0, 2) == " [")
+ {
+ db.names[k].first += " (";
+ db.names[k].second.insert(0, ")");
+ }
+ else if (db.names[k].second.front() == '(')
+ {
+ db.names[k].first += "(";
+ db.names[k].second.insert(0, ")");
+ }
+ if (first[1] != 'U' || db.names[k].first.substr(0, 12) != "objc_object<")
+ {
+ db.names[k].first.append("*");
+ }
+ else
+ {
+ db.names[k].first.replace(0, 11, "id");
+ }
+ db.subs.back().push_back(db.names[k]);
+ }
+ first = t;
+ }
+ break;
+ }
+ case 'R':
+ {
+ size_t k0 = db.names.size();
+ t = parse_type(first+1, last, db);
+ size_t k1 = db.names.size();
+ if (t != first+1)
+ {
+ db.subs.emplace_back(db.names.get_allocator());
+ for (size_t k = k0; k < k1; ++k)
+ {
+ if (db.names[k].second.substr(0, 2) == " [")
+ {
+ db.names[k].first += " (";
+ db.names[k].second.insert(0, ")");
+ }
+ else if (db.names[k].second.front() == '(')
+ {
+ db.names[k].first += "(";
+ db.names[k].second.insert(0, ")");
+ }
+ db.names[k].first.append("&");
+ db.subs.back().push_back(db.names[k]);
+ }
+ first = t;
+ }
+ break;
+ }
+ case 'T':
+ {
+ size_t k0 = db.names.size();
+ t = parse_template_param(first, last, db);
+ size_t k1 = db.names.size();
+ if (t != first)
+ {
+ db.subs.emplace_back(db.names.get_allocator());
+ for (size_t k = k0; k < k1; ++k)
+ db.subs.back().push_back(db.names[k]);
+ if (db.try_to_parse_template_args && k1 == k0+1)
+ {
+ const char* t1 = parse_template_args(t, last, db);
+ if (t1 != t)
+ {
+ auto args = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += std::move(args);
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ t = t1;
+ }
+ }
+ first = t;
+ }
+ break;
+ }
+ case 'U':
+ if (first+1 != last)
+ {
+ t = parse_source_name(first+1, last, db);
+ if (t != first+1)
+ {
+ const char* t2 = parse_type(t, last, db);
+ if (t2 != t)
+ {
+ auto type = db.names.back().move_full();
+ db.names.pop_back();
+ if (db.names.back().first.substr(0, 9) != "objcproto")
+ {
+ db.names.back() = type + " " + db.names.back().move_full();
+ }
+ else
+ {
+ auto proto = db.names.back().move_full();
+ db.names.pop_back();
+ t = parse_source_name(proto.data() + 9, proto.data() + proto.size(), db);
+ if (t != proto.data() + 9)
+ {
+ db.names.back() = type + "<" + db.names.back().move_full() + ">";
+ }
+ else
+ {
+ db.names.push_back(type + " " + proto);
+ }
+ }
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ first = t2;
+ }
+ }
+ }
+ break;
+ case 'S':
+ if (first+1 != last && first[1] == 't')
+ {
+ t = parse_name(first, last, db);
+ if (t != first)
+ {
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ first = t;
+ }
+ }
+ else
+ {
+ t = parse_substitution(first, last, db);
+ if (t != first)
+ {
+ first = t;
+ // Parsed a substitution. If the substitution is a
+ // <template-param> it might be followed by <template-args>.
+ t = parse_template_args(first, last, db);
+ if (t != first)
+ {
+ auto template_args = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += template_args;
+ // Need to create substitution for <template-template-param> <template-args>
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ first = t;
+ }
+ }
+ }
+ break;
+ case 'D':
+ if (first+1 != last)
+ {
+ switch (first[1])
+ {
+ case 'p':
+ {
+ size_t k0 = db.names.size();
+ t = parse_type(first+2, last, db);
+ size_t k1 = db.names.size();
+ if (t != first+2)
+ {
+ db.subs.emplace_back(db.names.get_allocator());
+ for (size_t k = k0; k < k1; ++k)
+ db.subs.back().push_back(db.names[k]);
+ first = t;
+ return first;
+ }
+ break;
+ }
+ case 't':
+ case 'T':
+ t = parse_decltype(first, last, db);
+ if (t != first)
+ {
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ first = t;
+ return first;
+ }
+ break;
+ case 'v':
+ t = parse_vector_type(first, last, db);
+ if (t != first)
+ {
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ first = t;
+ return first;
+ }
+ break;
+ }
+ }
+ // drop through
+ default:
+ // must check for builtin-types before class-enum-types to avoid
+ // ambiguities with operator-names
+ t = parse_builtin_type(first, last, db);
+ if (t != first)
+ {
+ first = t;
+ }
+ else
+ {
+ t = parse_name(first, last, db);
+ if (t != first)
+ {
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ first = t;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ return first;
+}
+
+// <operator-name>
+// ::= aa # &&
+// ::= ad # & (unary)
+// ::= an # &
+// ::= aN # &=
+// ::= aS # =
+// ::= cl # ()
+// ::= cm # ,
+// ::= co # ~
+// ::= cv <type> # (cast)
+// ::= 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 # >>=
+// ::= v <digit> <source-name> # vendor extended operator
+
+template <class C>
+const char*
+parse_operator_name(const char* first, const char* last, C& db)
+{
+ if (last - first >= 2)
+ {
+ switch (first[0])
+ {
+ case 'a':
+ switch (first[1])
+ {
+ case 'a':
+ db.names.push_back("operator&&");
+ first += 2;
+ break;
+ case 'd':
+ case 'n':
+ db.names.push_back("operator&");
+ first += 2;
+ break;
+ case 'N':
+ db.names.push_back("operator&=");
+ first += 2;
+ break;
+ case 'S':
+ db.names.push_back("operator=");
+ first += 2;
+ break;
+ }
+ break;
+ case 'c':
+ switch (first[1])
+ {
+ case 'l':
+ db.names.push_back("operator()");
+ first += 2;
+ break;
+ case 'm':
+ db.names.push_back("operator,");
+ first += 2;
+ break;
+ case 'o':
+ db.names.push_back("operator~");
+ first += 2;
+ break;
+ case 'v':
+ {
+ bool try_to_parse_template_args = db.try_to_parse_template_args;
+ db.try_to_parse_template_args = false;
+ const char* t = parse_type(first+2, last, db);
+ db.try_to_parse_template_args = try_to_parse_template_args;
+ if (t != first+2)
+ {
+ db.names.back().first.insert(0, "operator ");
+ db.parsed_ctor_dtor_cv = true;
+ first = t;
+ }
+ }
+ break;
+ }
+ break;
+ case 'd':
+ switch (first[1])
+ {
+ case 'a':
+ db.names.push_back("operator delete[]");
+ first += 2;
+ break;
+ case 'e':
+ db.names.push_back("operator*");
+ first += 2;
+ break;
+ case 'l':
+ db.names.push_back("operator delete");
+ first += 2;
+ break;
+ case 'v':
+ db.names.push_back("operator/");
+ first += 2;
+ break;
+ case 'V':
+ db.names.push_back("operator/=");
+ first += 2;
+ break;
+ }
+ break;
+ case 'e':
+ switch (first[1])
+ {
+ case 'o':
+ db.names.push_back("operator^");
+ first += 2;
+ break;
+ case 'O':
+ db.names.push_back("operator^=");
+ first += 2;
+ break;
+ case 'q':
+ db.names.push_back("operator==");
+ first += 2;
+ break;
+ }
+ break;
+ case 'g':
+ switch (first[1])
+ {
+ case 'e':
+ db.names.push_back("operator>=");
+ first += 2;
+ break;
+ case 't':
+ db.names.push_back("operator>");
+ first += 2;
+ break;
+ }
+ break;
+ case 'i':
+ if (first[1] == 'x')
+ {
+ db.names.push_back("operator[]");
+ first += 2;
+ }
+ break;
+ case 'l':
+ switch (first[1])
+ {
+ case 'e':
+ db.names.push_back("operator<=");
+ first += 2;
+ break;
+ case 's':
+ db.names.push_back("operator<<");
+ first += 2;
+ break;
+ case 'S':
+ db.names.push_back("operator<<=");
+ first += 2;
+ break;
+ case 't':
+ db.names.push_back("operator<");
+ first += 2;
+ break;
+ }
+ break;
+ case 'm':
+ switch (first[1])
+ {
+ case 'i':
+ db.names.push_back("operator-");
+ first += 2;
+ break;
+ case 'I':
+ db.names.push_back("operator-=");
+ first += 2;
+ break;
+ case 'l':
+ db.names.push_back("operator*");
+ first += 2;
+ break;
+ case 'L':
+ db.names.push_back("operator*=");
+ first += 2;
+ break;
+ case 'm':
+ db.names.push_back("operator--");
+ first += 2;
+ break;
+ }
+ break;
+ case 'n':
+ switch (first[1])
+ {
+ case 'a':
+ db.names.push_back("operator new[]");
+ first += 2;
+ break;
+ case 'e':
+ db.names.push_back("operator!=");
+ first += 2;
+ break;
+ case 'g':
+ db.names.push_back("operator-");
+ first += 2;
+ break;
+ case 't':
+ db.names.push_back("operator!");
+ first += 2;
+ break;
+ case 'w':
+ db.names.push_back("operator new");
+ first += 2;
+ break;
+ }
+ break;
+ case 'o':
+ switch (first[1])
+ {
+ case 'o':
+ db.names.push_back("operator||");
+ first += 2;
+ break;
+ case 'r':
+ db.names.push_back("operator|");
+ first += 2;
+ break;
+ case 'R':
+ db.names.push_back("operator|=");
+ first += 2;
+ break;
+ }
+ break;
+ case 'p':
+ switch (first[1])
+ {
+ case 'm':
+ db.names.push_back("operator->*");
+ first += 2;
+ break;
+ case 'l':
+ db.names.push_back("operator+");
+ first += 2;
+ break;
+ case 'L':
+ db.names.push_back("operator+=");
+ first += 2;
+ break;
+ case 'p':
+ db.names.push_back("operator++");
+ first += 2;
+ break;
+ case 's':
+ db.names.push_back("operator+");
+ first += 2;
+ break;
+ case 't':
+ db.names.push_back("operator->");
+ first += 2;
+ break;
+ }
+ break;
+ case 'q':
+ if (first[1] == 'u')
+ {
+ db.names.push_back("operator?");
+ first += 2;
+ }
+ break;
+ case 'r':
+ switch (first[1])
+ {
+ case 'm':
+ db.names.push_back("operator%");
+ first += 2;
+ break;
+ case 'M':
+ db.names.push_back("operator%=");
+ first += 2;
+ break;
+ case 's':
+ db.names.push_back("operator>>");
+ first += 2;
+ break;
+ case 'S':
+ db.names.push_back("operator>>=");
+ first += 2;
+ break;
+ }
+ break;
+ case 'v':
+ if (std::isdigit(first[1]))
+ {
+ const char* t = parse_source_name(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back().first.insert(0, "operator ");
+ first = t;
+ }
+ }
+ break;
+ }
+ }
+ return first;
+}
+
+template <class C>
+const char*
+parse_integer_literal(const char* first, const char* last, const typename C::String& lit, C& db)
+{
+ const char* t = parse_number(first, last);
+ if (t != first && t != last && *t == 'E')
+ {
+ if (lit.size() > 3)
+ db.names.push_back("(" + lit + ")");
+ else
+ db.names.emplace_back();
+ if (*first == 'n')
+ {
+ db.names.back().first += '-';
+ ++first;
+ }
+ db.names.back().first.append(first, t);
+ if (lit.size() <= 3)
+ db.names.back().first += lit;
+ first = t+1;
+ }
+ return first;
+}
+
+// <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
+
+template <class C>
+const char*
+parse_expr_primary(const char* first, const char* last, C& db)
+{
+ if (last - first >= 4 && *first == 'L')
+ {
+ switch (first[1])
+ {
+ case 'w':
+ {
+ const char* t = parse_integer_literal(first+2, last, "wchar_t", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'b':
+ if (first[3] == 'E')
+ {
+ switch (first[2])
+ {
+ case '0':
+ db.names.push_back("false");
+ first += 4;
+ break;
+ case '1':
+ db.names.push_back("true");
+ first += 4;
+ break;
+ }
+ }
+ break;
+ case 'c':
+ {
+ const char* t = parse_integer_literal(first+2, last, "char", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'a':
+ {
+ const char* t = parse_integer_literal(first+2, last, "signed char", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'h':
+ {
+ const char* t = parse_integer_literal(first+2, last, "unsigned char", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 's':
+ {
+ const char* t = parse_integer_literal(first+2, last, "short", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 't':
+ {
+ const char* t = parse_integer_literal(first+2, last, "unsigned short", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'i':
+ {
+ const char* t = parse_integer_literal(first+2, last, "", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'j':
+ {
+ const char* t = parse_integer_literal(first+2, last, "u", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'l':
+ {
+ const char* t = parse_integer_literal(first+2, last, "l", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'm':
+ {
+ const char* t = parse_integer_literal(first+2, last, "ul", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'x':
+ {
+ const char* t = parse_integer_literal(first+2, last, "ll", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'y':
+ {
+ const char* t = parse_integer_literal(first+2, last, "ull", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'n':
+ {
+ const char* t = parse_integer_literal(first+2, last, "__int128", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'o':
+ {
+ const char* t = parse_integer_literal(first+2, last, "unsigned __int128", db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'f':
+ {
+ const char* t = parse_floating_number<float>(first+2, last, db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'd':
+ {
+ const char* t = parse_floating_number<double>(first+2, last, db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case 'e':
+ {
+ const char* t = parse_floating_number<long double>(first+2, last, db);
+ if (t != first+2)
+ first = t;
+ }
+ break;
+ case '_':
+ if (first[2] == 'Z')
+ {
+ const char* t = parse_encoding(first+3, last, db);
+ if (t != first+3 && t != last && *t == 'E')
+ first = t+1;
+ }
+ break;
+ case 'T':
+ // Invalid mangled name per
+ // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
+ break;
+ default:
+ {
+ // might be named type
+ const char* t = parse_type(first+1, last, db);
+ if (t != first+1 && t != last)
+ {
+ if (*t != 'E')
+ {
+ const char* n = t;
+ for (; n != last && isdigit(*n); ++n)
+ ;
+ if (n != t && n != last && *n == 'E')
+ {
+ db.names.back() = "(" + db.names.back().move_full() + ")" + typename C::String(t, n);
+ first = n+1;
+ break;
+ }
+ }
+ else
+ {
+ first = t+1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return first;
+}
+
+template <class String>
+String
+base_name(String& s)
+{
+ if (s.empty())
+ return s;
+ if (s == "std::string")
+ {
+ s = "std::basic_string<char, std::char_traits<char>, std::allocator<char> >";
+ return "basic_string";
+ }
+ if (s == "std::istream")
+ {
+ s = "std::basic_istream<char, std::char_traits<char> >";
+ return "basic_istream";
+ }
+ if (s == "std::ostream")
+ {
+ s = "std::basic_ostream<char, std::char_traits<char> >";
+ return "basic_ostream";
+ }
+ if (s == "std::iostream")
+ {
+ s = "std::basic_iostream<char, std::char_traits<char> >";
+ return "basic_iostream";
+ }
+ const char* const pf = s.data();
+ const char* pe = pf + s.size();
+ if (pe[-1] == '>')
+ {
+ unsigned c = 1;
+ while (true)
+ {
+ if (--pe == pf)
+ return String();
+ if (pe[-1] == '<')
+ {
+ if (--c == 0)
+ {
+ --pe;
+ break;
+ }
+ }
+ else if (pe[-1] == '>')
+ ++c;
+ }
+ }
+ const char* p0 = pe - 1;
+ for (; p0 != pf; --p0)
+ {
+ if (*p0 == ':')
+ {
+ ++p0;
+ break;
+ }
+ }
+ return String(p0, pe);
+}
+
+// <ctor-dtor-name> ::= C1 # complete object constructor
+// ::= C2 # base object constructor
+// ::= C3 # complete object allocating constructor
+// extension ::= C5 # ?
+// ::= D0 # deleting destructor
+// ::= D1 # complete object destructor
+// ::= D2 # base object destructor
+// extension ::= D5 # ?
+
+template <class C>
+const char*
+parse_ctor_dtor_name(const char* first, const char* last, C& db)
+{
+ if (last-first >= 2 && !db.names.empty())
+ {
+ switch (first[0])
+ {
+ case 'C':
+ switch (first[1])
+ {
+ case '1':
+ case '2':
+ case '3':
+ case '5':
+ db.names.push_back(base_name(db.names.back().first));
+ first += 2;
+ db.parsed_ctor_dtor_cv = true;
+ break;
+ }
+ break;
+ case 'D':
+ switch (first[1])
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '5':
+ db.names.push_back("~" + base_name(db.names.back().first));
+ first += 2;
+ db.parsed_ctor_dtor_cv = true;
+ break;
+ }
+ break;
+ }
+ }
+ return first;
+}
+
+// <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
+
+template <class C>
+const char*
+parse_unnamed_type_name(const char* first, const char* last, C& db)
+{
+ if (last - first > 2 && first[0] == 'U')
+ {
+ char type = first[1];
+ switch (type)
+ {
+ case 't':
+ {
+ db.names.push_back(typename C::String("'unnamed"));
+ const char* t0 = first+2;
+ if (t0 == last)
+ {
+ db.names.pop_back();
+ return first;
+ }
+ if (std::isdigit(*t0))
+ {
+ const char* t1 = t0 + 1;
+ while (t1 != last && std::isdigit(*t1))
+ ++t1;
+ db.names.back().first.append(t0, t1);
+ t0 = t1;
+ }
+ db.names.back().first.push_back('\'');
+ if (t0 == last || *t0 != '_')
+ {
+ db.names.pop_back();
+ return first;
+ }
+ first = t0 + 1;
+ }
+ break;
+ case 'l':
+ {
+ db.names.push_back(typename C::String("'lambda'("));
+ const char* t0 = first+2;
+ if (first[2] == 'v')
+ {
+ db.names.back().first += ')';
+ ++t0;
+ }
+ else
+ {
+ const char* t1 = parse_type(t0, last, db);
+ if (t1 == t0)
+ {
+ db.names.pop_back();
+ return first;
+ }
+ auto tmp = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first.append(tmp);
+ t0 = t1;
+ while (true)
+ {
+ t1 = parse_type(t0, last, db);
+ if (t1 == t0)
+ break;
+ tmp = db.names.back().move_full();
+ db.names.pop_back();
+ if (!tmp.empty())
+ {
+ db.names.back().first.append(", ");
+ db.names.back().first.append(tmp);
+ }
+ t0 = t1;
+ }
+ db.names.back().first.append(")");
+ }
+ if (t0 == last || *t0 != 'E')
+ {
+ db.names.pop_back();
+ return first;
+ }
+ ++t0;
+ if (t0 == last)
+ {
+ db.names.pop_back();
+ return first;
+ }
+ if (std::isdigit(*t0))
+ {
+ const char* t1 = t0 + 1;
+ while (t1 != last && std::isdigit(*t1))
+ ++t1;
+ db.names.back().first.insert(db.names.back().first.begin()+7, t0, t1);
+ t0 = t1;
+ }
+ if (t0 == last || *t0 != '_')
+ {
+ db.names.pop_back();
+ return first;
+ }
+ first = t0 + 1;
+ }
+ break;
+ }
+ }
+ return first;
+}
+
+// <unqualified-name> ::= <operator-name>
+// ::= <ctor-dtor-name>
+// ::= <source-name>
+// ::= <unnamed-type-name>
+
+template <class C>
+const char*
+parse_unqualified_name(const char* first, const char* last, C& db)
+{
+ if (first != last)
+ {
+ const char* t;
+ switch (*first)
+ {
+ case 'C':
+ case 'D':
+ t = parse_ctor_dtor_name(first, last, db);
+ if (t != first)
+ first = t;
+ break;
+ case 'U':
+ t = parse_unnamed_type_name(first, last, db);
+ if (t != first)
+ first = t;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ t = parse_source_name(first, last, db);
+ if (t != first)
+ first = t;
+ break;
+ default:
+ t = parse_operator_name(first, last, db);
+ if (t != first)
+ first = t;
+ break;
+ };
+ }
+ return first;
+}
+
+// <unscoped-name> ::= <unqualified-name>
+// ::= St <unqualified-name> # ::std::
+// extension ::= StL<unqualified-name>
+
+template <class C>
+const char*
+parse_unscoped_name(const char* first, const char* last, C& db)
+{
+ if (last - first >= 2)
+ {
+ const char* t0 = first;
+ bool St = false;
+ if (first[0] == 'S' && first[1] == 't')
+ {
+ t0 += 2;
+ St = true;
+ if (t0 != last && *t0 == 'L')
+ ++t0;
+ }
+ const char* t1 = parse_unqualified_name(t0, last, db);
+ if (t1 != t0)
+ {
+ if (St)
+ db.names.back().first.insert(0, "std::");
+ first = t1;
+ }
+ }
+ return first;
+}
+
+// at <type> # alignof (a type)
+
+template <class C>
+const char*
+parse_alignof_type(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 'a' && first[1] == 't')
+ {
+ const char* t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back().first = "alignof (" + db.names.back().move_full() + ")";
+ first = t;
+ }
+ }
+ return first;
+}
+
+// az <expression> # alignof (a expression)
+
+template <class C>
+const char*
+parse_alignof_expr(const char* first, const char* last, C& db)
+{
+ if (last - first >= 3 && first[0] == 'a' && first[1] == 'z')
+ {
+ const char* t = parse_expression(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back().first = "alignof (" + db.names.back().move_full() + ")";
+ first = t;
+ }
+ }
+ return first;
+}
+
+template <class C>
+const char*
+parse_noexcept_expression(const char* first, const char* last, C& db)
+{
+ const char* t1 = parse_expression(first, last, db);
+ if (t1 != first)
+ {
+ db.names.back().first = "noexcept (" + db.names.back().move_full() + ")";
+ first = t1;
+ }
+ return first;
+}
+
+template <class C>
+const char*
+parse_prefix_expression(const char* first, const char* last, const typename C::String& op, C& db)
+{
+ const char* t1 = parse_expression(first, last, db);
+ if (t1 != first)
+ {
+ db.names.back().first = op + "(" + db.names.back().move_full() + ")";
+ first = t1;
+ }
+ return first;
+}
+
+template <class C>
+const char*
+parse_binary_expression(const char* first, const char* last, const typename C::String& op, C& db)
+{
+ const char* t1 = parse_expression(first, last, db);
+ if (t1 != first)
+ {
+ const char* t2 = parse_expression(t1, last, db);
+ if (t2 != t1)
+ {
+ auto op2 = db.names.back().move_full();
+ db.names.pop_back();
+ auto op1 = db.names.back().move_full();
+ auto& nm = db.names.back().first;
+ nm.clear();
+ if (op == ">")
+ nm += '(';
+ nm += "(" + op1 + ") " + op + " (" + op2 + ")";
+ if (op == ">")
+ nm += ')';
+ first = t2;
+ }
+ else
+ db.names.pop_back();
+ }
+ return first;
+}
+
+// <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>
+
+template <class C>
+const char*
+parse_expression(const char* first, const char* last, C& db)
+{
+ if (last - first >= 2)
+ {
+ const char* t = first;
+ bool parsed_gs = false;
+ if (last - first >= 4 && t[0] == 'g' && t[1] == 's')
+ {
+ t += 2;
+ parsed_gs = true;
+ }
+ switch (*t)
+ {
+ case 'L':
+ first = parse_expr_primary(first, last, db);
+ break;
+ case 'T':
+ first = parse_template_param(first, last, db);
+ break;
+ case 'f':
+ first = parse_function_param(first, last, db);
+ break;
+ case 'a':
+ switch (t[1])
+ {
+ case 'a':
+ t = parse_binary_expression(first+2, last, "&&", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'd':
+ t = parse_prefix_expression(first+2, last, "&", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'n':
+ t = parse_binary_expression(first+2, last, "&", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'N':
+ t = parse_binary_expression(first+2, last, "&=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'S':
+ t = parse_binary_expression(first+2, last, "=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 't':
+ first = parse_alignof_type(first, last, db);
+ break;
+ case 'z':
+ first = parse_alignof_expr(first, last, db);
+ break;
+ }
+ break;
+ case 'c':
+ switch (t[1])
+ {
+ case 'c':
+ first = parse_const_cast_expr(first, last, db);
+ break;
+ case 'l':
+ first = parse_call_expr(first, last, db);
+ break;
+ case 'm':
+ t = parse_binary_expression(first+2, last, ",", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'o':
+ t = parse_prefix_expression(first+2, last, "~", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'v':
+ first = parse_conversion_expr(first, last, db);
+ break;
+ }
+ break;
+ case 'd':
+ switch (t[1])
+ {
+ case 'a':
+ {
+ const char* t1 = parse_expression(t+2, last, db);
+ if (t1 != t+2)
+ {
+ db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) +
+ "delete[] " + db.names.back().move_full();
+ first = t1;
+ }
+ }
+ break;
+ case 'c':
+ first = parse_dynamic_cast_expr(first, last, db);
+ break;
+ case 'e':
+ t = parse_prefix_expression(first+2, last, "*", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'l':
+ {
+ const char* t1 = parse_expression(t+2, last, db);
+ if (t1 != t+2)
+ {
+ db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) +
+ "delete " + db.names.back().move_full();
+ first = t1;
+ }
+ }
+ break;
+ case 'n':
+ return parse_unresolved_name(first, last, db);
+ case 's':
+ first = parse_dot_star_expr(first, last, db);
+ break;
+ case 't':
+ first = parse_dot_expr(first, last, db);
+ break;
+ case 'v':
+ t = parse_binary_expression(first+2, last, "/", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'V':
+ t = parse_binary_expression(first+2, last, "/=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ }
+ break;
+ case 'e':
+ switch (t[1])
+ {
+ case 'o':
+ t = parse_binary_expression(first+2, last, "^", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'O':
+ t = parse_binary_expression(first+2, last, "^=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'q':
+ t = parse_binary_expression(first+2, last, "==", db);
+ if (t != first+2)
+ first = t;
+ break;
+ }
+ break;
+ case 'g':
+ switch (t[1])
+ {
+ case 'e':
+ t = parse_binary_expression(first+2, last, ">=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 't':
+ t = parse_binary_expression(first+2, last, ">", db);
+ if (t != first+2)
+ first = t;
+ break;
+ }
+ break;
+ case 'i':
+ if (t[1] == 'x')
+ {
+ const char* t1 = parse_expression(first+2, last, db);
+ if (t1 != first+2)
+ {
+ const char* t2 = parse_expression(t1, last, db);
+ if (t2 != t1)
+ {
+ auto op2 = db.names.back().move_full();
+ db.names.pop_back();
+ auto op1 = db.names.back().move_full();
+ db.names.back() = "(" + op1 + ")[" + op2 + "]";
+ first = t2;
+ }
+ else
+ db.names.pop_back();
+ }
+ }
+ break;
+ case 'l':
+ switch (t[1])
+ {
+ case 'e':
+ t = parse_binary_expression(first+2, last, "<=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 's':
+ t = parse_binary_expression(first+2, last, "<<", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'S':
+ t = parse_binary_expression(first+2, last, "<<=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 't':
+ t = parse_binary_expression(first+2, last, "<", db);
+ if (t != first+2)
+ first = t;
+ break;
+ }
+ break;
+ case 'm':
+ switch (t[1])
+ {
+ case 'i':
+ t = parse_binary_expression(first+2, last, "-", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'I':
+ t = parse_binary_expression(first+2, last, "-=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'l':
+ t = parse_binary_expression(first+2, last, "*", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'L':
+ t = parse_binary_expression(first+2, last, "*=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'm':
+ if (first+2 != last && first[2] == '_')
+ {
+ t = parse_prefix_expression(first+3, last, "--", db);
+ if (t != first+3)
+ first = t;
+ }
+ else
+ {
+ const char* t1 = parse_expression(first+2, last, db);
+ if (t1 != first+2)
+ {
+ db.names.back() = "(" + db.names.back().move_full() + ")--";
+ first = t1;
+ }
+ }
+ break;
+ }
+ break;
+ case 'n':
+ switch (t[1])
+ {
+ case 'a':
+ case 'w':
+ first = parse_new_expr(first, last, db);
+ break;
+ case 'e':
+ t = parse_binary_expression(first+2, last, "!=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'g':
+ t = parse_prefix_expression(first+2, last, "-", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 't':
+ t = parse_prefix_expression(first+2, last, "!", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'x':
+ t = parse_noexcept_expression(first+2, last, db);
+ if (t != first+2)
+ first = t;
+ break;
+ }
+ break;
+ case 'o':
+ switch (t[1])
+ {
+ case 'n':
+ return parse_unresolved_name(first, last, db);
+ case 'o':
+ t = parse_binary_expression(first+2, last, "||", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'r':
+ t = parse_binary_expression(first+2, last, "|", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'R':
+ t = parse_binary_expression(first+2, last, "|=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ }
+ break;
+ case 'p':
+ switch (t[1])
+ {
+ case 'm':
+ t = parse_binary_expression(first+2, last, "->*", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'l':
+ t = parse_binary_expression(first+2, last, "+", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'L':
+ t = parse_binary_expression(first+2, last, "+=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'p':
+ if (first+2 != last && first[2] == '_')
+ {
+ t = parse_prefix_expression(first+3, last, "++", db);
+ if (t != first+3)
+ first = t;
+ }
+ else
+ {
+ const char* t1 = parse_expression(first+2, last, db);
+ if (t1 != first+2)
+ {
+ db.names.back() = "(" + db.names.back().move_full() + ")++";
+ first = t1;
+ }
+ }
+ break;
+ case 's':
+ t = parse_prefix_expression(first+2, last, "+", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 't':
+ first = parse_arrow_expr(first, last, db);
+ break;
+ }
+ break;
+ case 'q':
+ if (t[1] == 'u')
+ {
+ const char* t1 = parse_expression(first+2, last, db);
+ if (t1 != first+2)
+ {
+ const char* t2 = parse_expression(t1, last, db);
+ if (t2 != t1)
+ {
+ const char* t3 = parse_expression(t2, last, db);
+ if (t3 != t2)
+ {
+ auto op3 = db.names.back().move_full();
+ db.names.pop_back();
+ auto op2 = db.names.back().move_full();
+ db.names.pop_back();
+ auto op1 = db.names.back().move_full();
+ db.names.back() = "(" + op1 + ") ? (" + op2 + ") : (" + op3 + ")";
+ first = t3;
+ }
+ else
+ {
+ db.names.pop_back();
+ db.names.pop_back();
+ }
+ }
+ else
+ db.names.pop_back();
+ }
+ }
+ break;
+ case 'r':
+ switch (t[1])
+ {
+ case 'c':
+ first = parse_reinterpret_cast_expr(first, last, db);
+ break;
+ case 'm':
+ t = parse_binary_expression(first+2, last, "%", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'M':
+ t = parse_binary_expression(first+2, last, "%=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 's':
+ t = parse_binary_expression(first+2, last, ">>", db);
+ if (t != first+2)
+ first = t;
+ break;
+ case 'S':
+ t = parse_binary_expression(first+2, last, ">>=", db);
+ if (t != first+2)
+ first = t;
+ break;
+ }
+ break;
+ case 's':
+ switch (t[1])
+ {
+ case 'c':
+ first = parse_static_cast_expr(first, last, db);
+ break;
+ case 'p':
+ first = parse_pack_expansion(first, last, db);
+ break;
+ case 'r':
+ return parse_unresolved_name(first, last, db);
+ case 't':
+ first = parse_sizeof_type_expr(first, last, db);
+ break;
+ case 'z':
+ first = parse_sizeof_expr_expr(first, last, db);
+ break;
+ case 'Z':
+ if (last - t >= 3)
+ {
+ switch (t[2])
+ {
+ case 'T':
+ first = parse_sizeof_param_pack_expr(first, last, db);
+ break;
+ case 'f':
+ first = parse_sizeof_function_param_pack_expr(first, last, db);
+ break;
+ }
+ }
+ break;
+ }
+ break;
+ case 't':
+ switch (t[1])
+ {
+ case 'e':
+ case 'i':
+ first = parse_typeid_expr(first, last, db);
+ break;
+ case 'r':
+ db.names.push_back("throw");
+ first += 2;
+ break;
+ case 'w':
+ first = parse_throw_expr(first, last, db);
+ break;
+ }
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return parse_unresolved_name(first, last, db);
+ }
+ }
+ return first;
+}
+
+// <template-arg> ::= <type> # type or template
+// ::= X <expression> E # expression
+// ::= <expr-primary> # simple expressions
+// ::= J <template-arg>* E # argument pack
+// ::= LZ <encoding> E # extension
+
+template <class C>
+const char*
+parse_template_arg(const char* first, const char* last, C& db)
+{
+ if (first != last)
+ {
+ const char* t;
+ switch (*first)
+ {
+ case 'X':
+ t = parse_expression(first+1, last, db);
+ if (t != first+1)
+ {
+ if (t != last && *t == 'E')
+ first = t+1;
+ }
+ break;
+ case 'J':
+ t = first+1;
+ if (t == last)
+ return first;
+ while (*t != 'E')
+ {
+ const char* t1 = parse_template_arg(t, last, db);
+ if (t1 == t)
+ return first;
+ t = t1;
+ }
+ first = t+1;
+ break;
+ case 'L':
+ // <expr-primary> or LZ <encoding> E
+ if (first+1 != last && first[1] == 'Z')
+ {
+ t = parse_encoding(first+2, last, db);
+ if (t != first+2 && t != last && *t == 'E')
+ first = t+1;
+ }
+ else
+ first = parse_expr_primary(first, last, db);
+ break;
+ default:
+ // <type>
+ first = parse_type(first, last, db);
+ break;
+ }
+ }
+ return first;
+}
+
+// <template-args> ::= I <template-arg>* E
+// extension, the abi says <template-arg>+
+
+template <class C>
+const char*
+parse_template_args(const char* first, const char* last, C& db)
+{
+ if (last - first >= 2 && *first == 'I')
+ {
+ if (db.tag_templates)
+ db.template_param.back().clear();
+ const char* t = first+1;
+ typename C::String args("<");
+ while (*t != 'E')
+ {
+ if (db.tag_templates)
+ db.template_param.emplace_back(db.names.get_allocator());
+ size_t k0 = db.names.size();
+ const char* t1 = parse_template_arg(t, last, db);
+ size_t k1 = db.names.size();
+ if (db.tag_templates)
+ db.template_param.pop_back();
+ if (t1 == t || t1 == last)
+ return first;
+ if (db.tag_templates)
+ {
+ db.template_param.back().emplace_back(db.names.get_allocator());
+ for (size_t k = k0; k < k1; ++k)
+ db.template_param.back().back().push_back(db.names[k]);
+ }
+ for (size_t k = k0; k < k1; ++k)
+ {
+ if (args.size() > 1)
+ args += ", ";
+ args += db.names[k].move_full();
+ }
+ for (; k1 != k0; --k1)
+ db.names.pop_back();
+ t = t1;
+ }
+ first = t + 1;
+ if (args.back() != '>')
+ args += ">";
+ else
+ args += " >";
+ db.names.push_back(std::move(args));
+
+ }
+ return first;
+}
+
+// <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>
+
+template <class C>
+const char*
+parse_nested_name(const char* first, const char* last, C& db)
+{
+ if (first != last && *first == 'N')
+ {
+ unsigned cv;
+ const char* t0 = parse_cv_qualifiers(first+1, last, cv);
+ if (t0 == last)
+ return first;
+ db.ref = 0;
+ if (*t0 == 'R')
+ {
+ db.ref = 1;
+ ++t0;
+ }
+ else if (*t0 == 'O')
+ {
+ db.ref = 2;
+ ++t0;
+ }
+ db.names.emplace_back();
+ if (last - t0 >= 2 && t0[0] == 'S' && t0[1] == 't')
+ {
+ t0 += 2;
+ db.names.back().first = "std";
+ }
+ if (t0 == last)
+ {
+ db.names.pop_back();
+ return first;
+ }
+ bool pop_subs = false;
+ while (*t0 != 'E')
+ {
+ const char* t1;
+ switch (*t0)
+ {
+ case 'S':
+ if (t0 + 1 != last && t0[1] == 't')
+ goto do_parse_unqualified_name;
+ t1 = parse_substitution(t0, last, db);
+ if (t1 != t0 && t1 != last)
+ {
+ auto name = db.names.back().move_full();
+ db.names.pop_back();
+ if (!db.names.back().first.empty())
+ {
+ db.names.back().first += "::" + name;
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ }
+ else
+ db.names.back().first = name;
+ pop_subs = true;
+ t0 = t1;
+ }
+ else
+ return first;
+ break;
+ case 'T':
+ t1 = parse_template_param(t0, last, db);
+ if (t1 != t0 && t1 != last)
+ {
+ auto name = db.names.back().move_full();
+ db.names.pop_back();
+ if (!db.names.back().first.empty())
+ db.names.back().first += "::" + name;
+ else
+ db.names.back().first = name;
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ pop_subs = true;
+ t0 = t1;
+ }
+ else
+ return first;
+ break;
+ case 'D':
+ if (t0 + 1 != last && t0[1] != 't' && t0[1] != 'T')
+ goto do_parse_unqualified_name;
+ t1 = parse_decltype(t0, last, db);
+ if (t1 != t0 && t1 != last)
+ {
+ auto name = db.names.back().move_full();
+ db.names.pop_back();
+ if (!db.names.back().first.empty())
+ db.names.back().first += "::" + name;
+ else
+ db.names.back().first = name;
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ pop_subs = true;
+ t0 = t1;
+ }
+ else
+ return first;
+ break;
+ case 'I':
+ t1 = parse_template_args(t0, last, db);
+ if (t1 != t0 && t1 != last)
+ {
+ auto name = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += name;
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ t0 = t1;
+ }
+ else
+ return first;
+ break;
+ case 'L':
+ if (++t0 == last)
+ return first;
+ break;
+ default:
+ do_parse_unqualified_name:
+ t1 = parse_unqualified_name(t0, last, db);
+ if (t1 != t0 && t1 != last)
+ {
+ auto name = db.names.back().move_full();
+ db.names.pop_back();
+ if (!db.names.back().first.empty())
+ db.names.back().first += "::" + name;
+ else
+ db.names.back().first = name;
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ pop_subs = true;
+ t0 = t1;
+ }
+ else
+ return first;
+ }
+ }
+ first = t0 + 1;
+ db.cv = cv;
+ if (pop_subs && !db.subs.empty())
+ db.subs.pop_back();
+ }
+ return first;
+}
+
+// <discriminator> := _ <non-negative number> # when number < 10
+// := __ <non-negative number> _ # when number >= 10
+// extension := decimal-digit+
+
+const char*
+parse_discriminator(const char* first, const char* last)
+{
+ // parse but ignore discriminator
+ if (first != last)
+ {
+ if (*first == '_')
+ {
+ const char* t1 = first+1;
+ if (t1 != last)
+ {
+ if (std::isdigit(*t1))
+ first = t1+1;
+ else if (*t1 == '_')
+ {
+ for (++t1; t1 != last && std::isdigit(*t1); ++t1)
+ ;
+ if (t1 != last && *t1 == '_')
+ first = t1 + 1;
+ }
+ }
+ }
+ else if (std::isdigit(*first))
+ {
+ const char* t1 = first+1;
+ for (; t1 != last && std::isdigit(*t1); ++t1)
+ ;
+ first = t1;
+ }
+ }
+ return first;
+}
+
+// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
+// := Z <function encoding> E s [<discriminator>]
+// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
+
+template <class C>
+const char*
+parse_local_name(const char* first, const char* last, C& db)
+{
+ if (first != last && *first == 'Z')
+ {
+ const char* t = parse_encoding(first+1, last, db);
+ if (t != first+1 && t != last && *t == 'E' && ++t != last)
+ {
+ switch (*t)
+ {
+ case 's':
+ first = parse_discriminator(t+1, last);
+ db.names.back().first.append("::string literal");
+ break;
+ case 'd':
+ if (++t != last)
+ {
+ const char* t1 = parse_number(t, last);
+ if (t1 != last && *t1 == '_')
+ {
+ t = t1 + 1;
+ t1 = parse_name(t, last, db);
+ if (t1 != t)
+ {
+ auto name = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first.append("::");
+ db.names.back().first.append(name);
+ first = t1;
+ }
+ else
+ db.names.pop_back();
+ }
+ }
+ break;
+ default:
+ {
+ const char* t1 = parse_name(t, last, db);
+ if (t1 != t)
+ {
+ // parse but ignore discriminator
+ first = parse_discriminator(t1, last);
+ auto name = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first.append("::");
+ db.names.back().first.append(name);
+ }
+ else
+ db.names.pop_back();
+ }
+ break;
+ }
+ }
+ }
+ return first;
+}
+
+// <name> ::= <nested-name> // N
+// ::= <local-name> # See Scope Encoding below // Z
+// ::= <unscoped-template-name> <template-args>
+// ::= <unscoped-name>
+
+// <unscoped-template-name> ::= <unscoped-name>
+// ::= <substitution>
+
+template <class C>
+const char*
+parse_name(const char* first, const char* last, C& db)
+{
+ if (last - first >= 2)
+ {
+ const char* t0 = first;
+ // extension: ignore L here
+ if (*t0 == 'L')
+ ++t0;
+ switch (*t0)
+ {
+ case 'N':
+ {
+ const char* t1 = parse_nested_name(t0, last, db);
+ if (t1 != t0)
+ first = t1;
+ break;
+ }
+ case 'Z':
+ {
+ const char* t1 = parse_local_name(t0, last, db);
+ if (t1 != t0)
+ first = t1;
+ break;
+ }
+ default:
+ {
+ const char* t1 = parse_unscoped_name(t0, last, db);
+ if (t1 != t0)
+ {
+ if (t1 != last && *t1 == 'I') // <unscoped-template-name> <template-args>
+ {
+ db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
+ t0 = t1;
+ t1 = parse_template_args(t0, last, db);
+ if (t1 != t0)
+ {
+ auto tmp = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += tmp;
+ first = t1;
+ }
+ }
+ else // <unscoped-name>
+ first = t1;
+ }
+ else
+ { // try <substitution> <template-args>
+ t1 = parse_substitution(t0, last, db);
+ if (t1 != t0 && t1 != last && *t1 == 'I')
+ {
+ t0 = t1;
+ t1 = parse_template_args(t0, last, db);
+ if (t1 != t0)
+ {
+ auto tmp = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first += tmp;
+ first = t1;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ return first;
+}
+
+// <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
+
+const char*
+parse_call_offset(const char* first, const char* last)
+{
+ if (first != last)
+ {
+ switch (*first)
+ {
+ case 'h':
+ {
+ const char* t = parse_number(first + 1, last);
+ if (t != first + 1 && t != last && *t == '_')
+ first = t + 1;
+ }
+ break;
+ case 'v':
+ {
+ const char* t = parse_number(first + 1, last);
+ if (t != first + 1 && t != last && *t == '_')
+ {
+ const char* t2 = parse_number(++t, last);
+ if (t2 != t && t2 != last && *t2 == '_')
+ first = t2 + 1;
+ }
+ }
+ break;
+ }
+ }
+ return first;
+}
+
+// <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
+// ::= GV <object name> # Guard variable for one-time initialization
+// # No <type>
+// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
+// extension ::= GR <object name> # reference temporary for object
+
+template <class C>
+const char*
+parse_special_name(const char* first, const char* last, C& db)
+{
+ if (last - first > 2)
+ {
+ const char* t;
+ switch (*first)
+ {
+ case 'T':
+ switch (first[1])
+ {
+ case 'V':
+ // TV <type> # virtual table
+ t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back().first.insert(0, "vtable for ");
+ first = t;
+ }
+ break;
+ case 'T':
+ // TT <type> # VTT structure (construction vtable index)
+ t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back().first.insert(0, "VTT for ");
+ first = t;
+ }
+ break;
+ case 'I':
+ // TI <type> # typeinfo structure
+ t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back().first.insert(0, "typeinfo for ");
+ first = t;
+ }
+ break;
+ case 'S':
+ // TS <type> # typeinfo name (null-terminated byte string)
+ t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back().first.insert(0, "typeinfo name for ");
+ first = t;
+ }
+ break;
+ case 'c':
+ // Tc <call-offset> <call-offset> <base encoding>
+ {
+ const char* t0 = parse_call_offset(first+2, last);
+ if (t0 == first+2)
+ break;
+ const char* t1 = parse_call_offset(t0, last);
+ if (t1 == t0)
+ break;
+ t = parse_encoding(t1, last, db);
+ if (t != t1)
+ {
+ db.names.back().first.insert(0, "covariant return thunk to ");
+ first = t;
+ }
+ }
+ break;
+ case 'C':
+ // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
+ t = parse_type(first+2, last, db);
+ if (t != first+2)
+ {
+ const char* t0 = parse_number(t, last);
+ if (t0 != t && t0 != last && *t0 == '_')
+ {
+ const char* t1 = parse_type(++t0, last, db);
+ if (t1 != t0)
+ {
+ auto left = db.names.back().move_full();
+ db.names.pop_back();
+ db.names.back().first = "construction vtable for " +
+ std::move(left) + "-in-" +
+ db.names.back().move_full();
+ first = t1;
+ }
+ }
+ }
+ break;
+ default:
+ // T <call-offset> <base encoding>
+ {
+ const char* t0 = parse_call_offset(first+1, last);
+ if (t0 == first+1)
+ break;
+ t = parse_encoding(t0, last, db);
+ if (t != t0)
+ {
+ if (first[2] == 'v')
+ {
+ db.names.back().first.insert(0, "virtual thunk to ");
+ first = t;
+ }
+ else
+ {
+ db.names.back().first.insert(0, "non-virtual thunk to ");
+ first = t;
+ }
+ }
+ }
+ break;
+ }
+ break;
+ case 'G':
+ switch (first[1])
+ {
+ case 'V':
+ // GV <object name> # Guard variable for one-time initialization
+ t = parse_name(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back().first.insert(0, "guard variable for ");
+ first = t;
+ }
+ break;
+ case 'R':
+ // extension ::= GR <object name> # reference temporary for object
+ t = parse_name(first+2, last, db);
+ if (t != first+2)
+ {
+ db.names.back().first.insert(0, "reference temporary for ");
+ first = t;
+ }
+ break;
+ }
+ break;
+ }
+ }
+ return first;
+}
+
+// <encoding> ::= <function name> <bare-function-type>
+// ::= <data name>
+// ::= <special-name>
+
+template <class C>
+const char*
+parse_encoding(const char* first, const char* last, C& db)
+{
+ if (first != last)
+ {
+ switch (*first)
+ {
+ case 'G':
+ case 'T':
+ first = parse_special_name(first, last, db);
+ break;
+ default:
+ {
+ const char* t = parse_name(first, last, db);
+ unsigned cv = db.cv;
+ unsigned ref = db.ref;
+ if (t != first)
+ {
+ if (t != last && *t != 'E' && *t != '.')
+ {
+ bool tag_templates = db.tag_templates;
+ db.tag_templates = false;
+ const char* t2;
+ typename C::String ret2;
+ const typename C::String& nm = db.names.back().first;
+ if (!db.parsed_ctor_dtor_cv && nm.back() == '>' && nm[nm.size()-2] != '-'
+ && nm[nm.size()-2] != '>')
+ {
+ t2 = parse_type(t, last, db);
+ if (t2 == t)
+ return first;
+ auto ret1 = std::move(db.names.back().first);
+ ret2 = std::move(db.names.back().second);
+ if (ret2.empty())
+ ret1 += ' ';
+ db.names.pop_back();
+ db.names.back().first.insert(0, ret1);
+ t = t2;
+ }
+ db.names.back().first += '(';
+ if (t != last && *t == 'v')
+ {
+ ++t;
+ }
+ else
+ {
+ bool first_arg = true;
+ while (true)
+ {
+ size_t k0 = db.names.size();
+ t2 = parse_type(t, last, db);
+ size_t k1 = db.names.size();
+ if (t2 == t)
+ break;
+ if (k1 > k0)
+ {
+ typename C::String tmp;
+ for (size_t k = k0; k < k1; ++k)
+ {
+ if (!tmp.empty())
+ tmp += ", ";
+ tmp += db.names[k].move_full();
+ }
+ for (size_t k = k0; k < k1; ++k)
+ db.names.pop_back();
+ if (!tmp.empty())
+ {
+ if (!first_arg)
+ db.names.back().first += ", ";
+ else
+ first_arg = false;
+ db.names.back().first += tmp;
+ }
+ }
+ t = t2;
+ }
+ }
+ db.names.back().first += ')';
+ if (cv & 1)
+ db.names.back().first.append(" const");
+ if (cv & 2)
+ db.names.back().first.append(" volatile");
+ if (cv & 4)
+ db.names.back().first.append(" restrict");
+ if (ref == 1)
+ db.names.back().first.append(" &");
+ else if (ref == 2)
+ db.names.back().first.append(" &&");
+ db.names.back().first += ret2;
+ first = t;
+ db.tag_templates = tag_templates;
+ }
+ else
+ first = t;
+ }
+ break;
+ }
+ }
+ }
+ return first;
+}
+
+// _block_invoke
+// _block_invoke<decimal-digit>+
+// _block_invoke_<decimal-digit>+
+
+template <class C>
+const char*
+parse_block_invoke(const char* first, const char* last, C& db)
+{
+ if (last - first >= 13)
+ {
+ const char test[] = "_block_invoke";
+ const char* t = first;
+ for (int i = 0; i < 13; ++i, ++t)
+ {
+ if (*t != test[i])
+ return first;
+ }
+ if (t != last)
+ {
+ if (*t == '_')
+ {
+ // must have at least 1 decimal digit
+ if (++t == last || !std::isdigit(*t))
+ return first;
+ ++t;
+ }
+ // parse zero or more digits
+ while (t != last && isdigit(*t))
+ ++t;
+ }
+ db.names.back().first.insert(0, "invocation function for block in ");
+ first = t;
+ }
+ return first;
+}
+
+// extension
+// <dot-suffix> := .<anything and everything>
+
+template <class C>
+const char*
+parse_dot_suffix(const char* first, const char* last, C& db)
+{
+ if (first != last && *first == '.')
+ {
+ db.names.back().first += " (" + typename C::String(first, last) + ")";
+ first = last;
+ }
+ return first;
+}
+
+// <block-involcaton-function> ___Z<encoding>_block_invoke
+// <block-involcaton-function> ___Z<encoding>_block_invoke<decimal-digit>+
+// <block-involcaton-function> ___Z<encoding>_block_invoke_<decimal-digit>+
+// <mangled-name> ::= _Z<encoding>
+// ::= <type>
+
+template <class C>
+void
+demangle(const char* first, const char* last, C& db, int& status)
+{
+ if (first >= last)
+ {
+ status = invalid_mangled_name;
+ return;
+ }
+ if (*first == '_')
+ {
+ if (last - first >= 4)
+ {
+ if (first[1] == 'Z')
+ {
+ const char* t = parse_encoding(first+2, last, db);
+ if (t != first+2 && t != last && *t == '.')
+ t = parse_dot_suffix(t, last, db);
+ if (t != last)
+ status = invalid_mangled_name;
+ }
+ else if (first[1] == '_' && first[2] == '_' && first[3] == 'Z')
+ {
+ const char* t = parse_encoding(first+4, last, db);
+ if (t != first+4 && t != last)
+ {
+ const char* t1 = parse_block_invoke(t, last, db);
+ if (t1 != last)
+ status = invalid_mangled_name;
+ }
+ else
+ status = invalid_mangled_name;
+ }
+ else
+ status = invalid_mangled_name;
+ }
+ else
+ status = invalid_mangled_name;
+ }
+ else
+ {
+ const char* t = parse_type(first, last, db);
+ if (t != last)
+ status = invalid_mangled_name;
+ }
+ if (status == success && db.names.empty())
+ status = invalid_mangled_name;
+}
+
+template <std::size_t N>
+class arena
+{
+ static const std::size_t alignment = 16;
+ alignas(alignment) char buf_[N];
+ char* ptr_;
+
+ std::size_t
+ align_up(std::size_t n) noexcept
+ {return n + (alignment-1) & ~(alignment-1);}
+
+ bool
+ pointer_in_buffer(char* p) noexcept
+ {return buf_ <= p && p <= buf_ + N;}
+
+public:
+ arena() noexcept : ptr_(buf_) {}
+ ~arena() {ptr_ = nullptr;}
+ arena(const arena&) = delete;
+ arena& operator=(const arena&) = delete;
+
+ char* allocate(std::size_t n);
+ void deallocate(char* p, std::size_t n) noexcept;
+
+ static constexpr std::size_t size() {return N;}
+ std::size_t used() const {return static_cast<std::size_t>(ptr_ - buf_);}
+ void reset() {ptr_ = buf_;}
+};
+
+template <std::size_t N>
+char*
+arena<N>::allocate(std::size_t n)
+{
+ n = align_up(n);
+ if (static_cast<std::size_t>(buf_ + N - ptr_) >= n)
+ {
+ char* r = ptr_;
+ ptr_ += n;
+ return r;
+ }
+ return static_cast<char*>(std::malloc(n));
+}
+
+template <std::size_t N>
+void
+arena<N>::deallocate(char* p, std::size_t n) noexcept
+{
+ if (pointer_in_buffer(p))
+ {
+ n = align_up(n);
+ if (p + n == ptr_)
+ ptr_ = p;
+ }
+ else
+ std::free(p);
+}
+
+template <class T, std::size_t N>
+class short_alloc
+{
+ arena<N>& a_;
+public:
+ typedef T value_type;
+
+public:
+ template <class _Up> struct rebind {typedef short_alloc<_Up, N> other;};
+
+ short_alloc(arena<N>& a) noexcept : a_(a) {}
+ template <class U>
+ short_alloc(const short_alloc<U, N>& a) noexcept
+ : a_(a.a_) {}
+ short_alloc(const short_alloc&) = default;
+ short_alloc& operator=(const short_alloc&) = delete;
+
+ T* allocate(std::size_t n)
+ {
+ return reinterpret_cast<T*>(a_.allocate(n*sizeof(T)));
+ }
+ void deallocate(T* p, std::size_t n) noexcept
+ {
+ a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
+ }
+
+ template <class T1, std::size_t N1, class U, std::size_t M>
+ friend
+ bool
+ operator==(const short_alloc<T1, N1>& x, const short_alloc<U, M>& y) noexcept;
+
+ template <class U, std::size_t M> friend class short_alloc;
+};
+
+template <class T, std::size_t N, class U, std::size_t M>
+inline
+bool
+operator==(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
+{
+ return N == M && &x.a_ == &y.a_;
+}
+
+template <class T, std::size_t N, class U, std::size_t M>
+inline
+bool
+operator!=(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
+{
+ return !(x == y);
+}
+
+template <class T>
+class malloc_alloc
+{
+public:
+ typedef T value_type;
+
+ malloc_alloc() = default;
+ template <class U> malloc_alloc(const malloc_alloc<U>&) noexcept {}
+
+ T* allocate(std::size_t n)
+ {
+ return static_cast<T*>(std::malloc(n*sizeof(T)));
+ }
+ void deallocate(T* p, std::size_t) noexcept
+ {
+ std::free(p);
+ }
+};
+
+template <class T, class U>
+inline
+bool
+operator==(const malloc_alloc<T>&, const malloc_alloc<U>&) noexcept
+{
+ return true;
+}
+
+template <class T, class U>
+inline
+bool
+operator!=(const malloc_alloc<T>& x, const malloc_alloc<U>& y) noexcept
+{
+ return !(x == y);
+}
+
+const size_t bs = 4 * 1024;
+template <class T> using Alloc = short_alloc<T, bs>;
+template <class T> using Vector = std::vector<T, Alloc<T>>;
+using String = std::basic_string<char, std::char_traits<char>, malloc_alloc<char>>;
+
+struct string_pair
+{
+ String first;
+ String second;
+
+ string_pair() = default;
+ string_pair(String f) : first(std::move(f)) {}
+ string_pair(String f, String s)
+ : first(std::move(f)), second(std::move(s)) {}
+ template <size_t N>
+ string_pair(const char (&s)[N]) : first(s, N-1) {}
+
+ size_t size() const {return first.size() + second.size();}
+ String full() const {return first + second;}
+ String move_full() {return std::move(first) + std::move(second);}
+};
+
+struct Db
+{
+ typedef String String;
+ typedef Vector<string_pair> sub_type;
+ typedef Vector<sub_type> template_param_type;
+ Vector<string_pair> names;
+ Vector<sub_type> subs;
+ Vector<template_param_type> template_param;
+ unsigned cv;
+ unsigned ref;
+ bool parsed_ctor_dtor_cv;
+ bool tag_templates;
+ bool fix_forward_references;
+ bool try_to_parse_template_args;
+
+ template <size_t N>
+ Db(arena<N>& ar) :
+ names(ar),
+ subs(0, names, ar),
+ template_param(0, subs, ar)
+ {}
+};
+
+char*
+__cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status)
+{
+ if (mangled_name == nullptr || (buf != nullptr && n == nullptr))
+ {
+ if (status)
+ *status = invalid_args;
+ return nullptr;
+ }
+ size_t internal_size = buf != nullptr ? *n : 0;
+ arena<bs> a;
+ Db db(a);
+ db.cv = 0;
+ db.ref = 0;
+ db.parsed_ctor_dtor_cv = false;
+ db.tag_templates = true;
+ db.template_param.emplace_back(a);
+ db.fix_forward_references = false;
+ db.try_to_parse_template_args = true;
+ int internal_status = success;
+ size_t len = std::strlen(mangled_name);
+ demangle(mangled_name, mangled_name + len, db,
+ internal_status);
+ if (internal_status == success && db.fix_forward_references &&
+ !db.template_param.empty() && !db.template_param.front().empty())
+ {
+ db.fix_forward_references = false;
+ db.tag_templates = false;
+ db.names.clear();
+ db.subs.clear();
+ demangle(mangled_name, mangled_name + len, db, internal_status);
+ if (db.fix_forward_references)
+ internal_status = invalid_mangled_name;
+ }
+ if (internal_status == success)
+ {
+ size_t sz = db.names.back().size() + 1;
+ if (sz > internal_size)
+ {
+ char* newbuf = static_cast<char*>(std::realloc(buf, sz));
+ if (newbuf == nullptr)
+ {
+ internal_status = memory_alloc_failure;
+ buf = nullptr;
+ }
+ else
+ {
+ buf = newbuf;
+ if (n != nullptr)
+ *n = sz;
+ }
+ }
+ if (buf != nullptr)
+ {
+ db.names.back().first += db.names.back().second;
+ std::memcpy(buf, db.names.back().first.data(), sz-1);
+ buf[sz-1] = char(0);
+ }
+ }
+ else
+ buf = nullptr;
+ if (status)
+ *status = internal_status;
+ return buf;
+}
+
+} // unnamed namespace
+
+#endif
#include "llvm/ADT/DenseMap.h"
@@ -199,7 +4888,11 @@ 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);
+#else
char *demangled_name = abi::__cxa_demangle (mangled_cstr, NULL, NULL, NULL);
+#endif
if (demangled_name)
{
diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp
index 4252ed4cb6c6..3f3be9360efa 100644
--- a/source/Core/Module.cpp
+++ b/source/Core/Module.cpp
@@ -9,6 +9,7 @@
#include "lldb/lldb-python.h"
+#include "lldb/Core/AddressResolverFileLine.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/DataBuffer.h"
@@ -448,7 +449,8 @@ Module::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr)
}
uint32_t
-Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
+Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc,
+ bool resolve_tail_call_address)
{
Mutex::Locker locker (m_mutex);
uint32_t resolved_flags = 0;
@@ -467,6 +469,10 @@ Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve
sc.module_sp = shared_from_this();
resolved_flags |= eSymbolContextModule;
+ SymbolVendor* sym_vendor = GetSymbolVendor();
+ if (!sym_vendor)
+ return resolved_flags;
+
// Resolve the compile unit, function, block, line table or line
// entry if requested.
if (resolve_scope & eSymbolContextCompUnit ||
@@ -474,25 +480,92 @@ Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve
resolve_scope & eSymbolContextBlock ||
resolve_scope & eSymbolContextLineEntry )
{
- SymbolVendor *symbols = GetSymbolVendor ();
- if (symbols)
- resolved_flags |= symbols->ResolveSymbolContext (so_addr, resolve_scope, sc);
+ resolved_flags |= sym_vendor->ResolveSymbolContext (so_addr, resolve_scope, sc);
}
// Resolve the symbol if requested, but don't re-look it up if we've already found it.
if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol))
{
- SymbolVendor* sym_vendor = GetSymbolVendor();
- if (sym_vendor)
+ Symtab *symtab = sym_vendor->GetSymtab();
+ if (symtab && so_addr.IsSectionOffset())
{
- Symtab *symtab = sym_vendor->GetSymtab();
- if (symtab)
+ sc.symbol = symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
+ if (!sc.symbol &&
+ resolve_scope & eSymbolContextFunction && !(resolved_flags & eSymbolContextFunction))
+ {
+ bool verify_unique = false; // No need to check again since ResolveSymbolContext failed to find a symbol at this address.
+ if (ObjectFile *obj_file = sc.module_sp->GetObjectFile())
+ sc.symbol = obj_file->ResolveSymbolForAddress(so_addr, verify_unique);
+ }
+
+ if (sc.symbol)
{
- if (so_addr.IsSectionOffset())
+ if (sc.symbol->IsSynthetic())
{
- sc.symbol = symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
- if (sc.symbol)
- resolved_flags |= eSymbolContextSymbol;
+ // We have a synthetic symbol so lets check if the object file
+ // from the symbol file in the symbol vendor is different than
+ // the object file for the module, and if so search its symbol
+ // table to see if we can come up with a better symbol. For example
+ // dSYM files on MacOSX have an unstripped symbol table inside of
+ // them.
+ ObjectFile *symtab_objfile = symtab->GetObjectFile();
+ if (symtab_objfile && symtab_objfile->IsStripped())
+ {
+ SymbolFile *symfile = sym_vendor->GetSymbolFile();
+ if (symfile)
+ {
+ ObjectFile *symfile_objfile = symfile->GetObjectFile();
+ if (symfile_objfile != symtab_objfile)
+ {
+ Symtab *symfile_symtab = symfile_objfile->GetSymtab();
+ if (symfile_symtab)
+ {
+ Symbol *symbol = symfile_symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
+ if (symbol && !symbol->IsSynthetic())
+ {
+ sc.symbol = symbol;
+ }
+ }
+ }
+ }
+ }
+ }
+ resolved_flags |= eSymbolContextSymbol;
+ }
+ }
+ }
+
+ // For function symbols, so_addr may be off by one. This is a convention consistent
+ // with FDE row indices in eh_frame sections, but requires extra logic here to permit
+ // symbol lookup for disassembly and unwind.
+ if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol) &&
+ resolve_tail_call_address && so_addr.IsSectionOffset())
+ {
+ Address previous_addr = so_addr;
+ previous_addr.Slide(-1);
+
+ bool do_resolve_tail_call_address = false; // prevent recursion
+ const uint32_t flags = ResolveSymbolContextForAddress(previous_addr, resolve_scope, sc,
+ do_resolve_tail_call_address);
+ if (flags & eSymbolContextSymbol)
+ {
+ AddressRange addr_range;
+ if (sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range))
+ {
+ if (addr_range.GetBaseAddress().GetSection() == so_addr.GetSection())
+ {
+ // If the requested address is one past the address range of a function (i.e. a tail call),
+ // or the decremented address is the start of a function (i.e. some forms of trampoline),
+ // indicate that the symbol has been resolved.
+ if (so_addr.GetOffset() == addr_range.GetBaseAddress().GetOffset() ||
+ so_addr.GetOffset() == addr_range.GetBaseAddress().GetOffset() + addr_range.GetByteSize())
+ {
+ resolved_flags |= flags;
+ }
+ }
+ else
+ {
+ sc.symbol = nullptr; // Don't trust the symbol if the sections didn't match.
}
}
}
@@ -573,7 +646,7 @@ Module::FindCompileUnits (const FileSpec &path,
const size_t num_compile_units = GetNumCompileUnits();
SymbolContext sc;
sc.module_sp = shared_from_this();
- const bool compare_directory = path.GetDirectory();
+ const bool compare_directory = (bool)path.GetDirectory();
for (size_t i=0; i<num_compile_units; ++i)
{
sc.comp_unit = GetCompileUnitAtIndex(i).get();
@@ -752,6 +825,27 @@ Module::FindFunctions (const RegularExpression& regex,
return sc_list.GetSize() - start_size;
}
+void
+Module::FindAddressesForLine (const lldb::TargetSP target_sp,
+ const FileSpec &file, uint32_t line,
+ Function *function,
+ std::vector<Address> &output_local, std::vector<Address> &output_extern)
+{
+ SearchFilterByModule filter(target_sp, m_file);
+ AddressResolverFileLine resolver(file, line, true);
+ resolver.ResolveAddress (filter);
+
+ for (size_t n=0;n<resolver.GetNumberOfAddresses();n++)
+ {
+ Address addr = resolver.GetAddressRangeAtIndex(n).GetBaseAddress();
+ Function *f = addr.CalculateSymbolContextFunction();
+ if (f && f == function)
+ output_local.push_back (addr);
+ else
+ output_extern.push_back (addr);
+ }
+}
+
size_t
Module::FindTypes_Impl (const SymbolContext& sc,
const ConstString &name,
@@ -1447,14 +1541,14 @@ Module::MatchesModuleSpec (const ModuleSpec &module_ref)
const FileSpec &file_spec = module_ref.GetFileSpec();
if (file_spec)
{
- if (!FileSpec::Equal (file_spec, m_file, file_spec.GetDirectory()))
+ if (!FileSpec::Equal (file_spec, m_file, (bool)file_spec.GetDirectory()))
return false;
}
const FileSpec &platform_file_spec = module_ref.GetPlatformFileSpec();
if (platform_file_spec)
{
- if (!FileSpec::Equal (platform_file_spec, GetPlatformFileSpec (), platform_file_spec.GetDirectory()))
+ if (!FileSpec::Equal (platform_file_spec, GetPlatformFileSpec (), (bool)platform_file_spec.GetDirectory()))
return false;
}
@@ -1606,4 +1700,4 @@ Module::PrepareForFunctionNameLookup (const ConstString &name,
lookup_name = name;
match_name_after_lookup = false;
}
-} \ No newline at end of file
+}
diff --git a/source/Core/ModuleList.cpp b/source/Core/ModuleList.cpp
index ebc6702d3a90..215611e42429 100644
--- a/source/Core/ModuleList.cpp
+++ b/source/Core/ModuleList.cpp
@@ -663,7 +663,19 @@ ModuleList::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const
return false;
}
-
+void
+ModuleList::FindAddressesForLine (const lldb::TargetSP target_sp,
+ const FileSpec &file, uint32_t line,
+ Function *function,
+ std::vector<Address> &output_local, std::vector<Address> &output_extern)
+{
+ Mutex::Locker locker(m_modules_mutex);
+ collection::const_iterator pos, end = m_modules.end();
+ for (pos = m_modules.begin(); pos != end; ++pos)
+ {
+ (*pos)->FindAddressesForLine(target_sp, file, line, function, output_local, output_extern);
+ }
+}
ModuleSP
ModuleList::FindFirstModule (const ModuleSpec &module_spec) const
diff --git a/source/Core/Opcode.cpp b/source/Core/Opcode.cpp
index d9878656e3f1..978a110150f9 100644
--- a/source/Core/Opcode.cpp
+++ b/source/Core/Opcode.cpp
@@ -31,18 +31,18 @@ Opcode::Dump (Stream *s, uint32_t min_byte_width)
int bytes_written = 0;
switch (m_type)
{
- case Opcode::eTypeInvalid:
- bytes_written = s->PutCString ("<invalid>");
+ case Opcode::eTypeInvalid:
+ bytes_written = s->PutCString ("<invalid>");
break;
- case Opcode::eType8:
- bytes_written = s->Printf ("0x%2.2x", m_data.inst8);
+ case Opcode::eType8:
+ bytes_written = s->Printf ("0x%2.2x", m_data.inst8);
break;
case Opcode::eType16:
- bytes_written = s->Printf ("0x%4.4x", m_data.inst16);
+ bytes_written = s->Printf ("0x%4.4x", m_data.inst16);
break;
case Opcode::eType16_2:
case Opcode::eType32:
- bytes_written = s->Printf ("0x%8.8x", m_data.inst32);
+ bytes_written = s->Printf ("0x%8.8x", m_data.inst32);
break;
case Opcode::eType64:
@@ -55,12 +55,12 @@ Opcode::Dump (Stream *s, uint32_t min_byte_width)
{
if (i > 0)
bytes_written += s->PutChar (' ');
- bytes_written += s->Printf ("%2.2x", m_data.inst.bytes[i]);
+ bytes_written += s->Printf ("%2.2x", m_data.inst.bytes[i]);
}
}
break;
}
-
+
// 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)
@@ -89,7 +89,7 @@ uint32_t
Opcode::GetData (DataExtractor &data) const
{
uint32_t byte_size = GetByteSize ();
-
+
DataBufferSP buffer_sp;
if (byte_size > 0)
{
@@ -97,7 +97,7 @@ Opcode::GetData (DataExtractor &data) const
{
case Opcode::eTypeInvalid:
break;
-
+
case Opcode::eType8: buffer_sp.reset (new DataBufferHeap (&m_data.inst8, byte_size)); break;
case Opcode::eType16: buffer_sp.reset (new DataBufferHeap (&m_data.inst16, byte_size)); break;
case Opcode::eType16_2:
@@ -119,7 +119,7 @@ Opcode::GetData (DataExtractor &data) const
break;
}
}
-
+
if (buffer_sp)
{
data.SetByteOrder(GetDataByteOrder());
diff --git a/source/Core/PluginManager.cpp b/source/Core/PluginManager.cpp
index 7a2d3772e6c3..813cec227525 100644
--- a/source/Core/PluginManager.cpp
+++ b/source/Core/PluginManager.cpp
@@ -854,6 +854,111 @@ PluginManager::GetLanguageRuntimeCreateCallbackForPluginName (const ConstString
return NULL;
}
+#pragma mark SystemRuntime
+
+
+struct SystemRuntimeInstance
+{
+ SystemRuntimeInstance() :
+ name(),
+ description(),
+ create_callback(NULL)
+ {
+ }
+
+ ConstString name;
+ std::string description;
+ SystemRuntimeCreateInstance create_callback;
+};
+
+typedef std::vector<SystemRuntimeInstance> SystemRuntimeInstances;
+
+static Mutex &
+GetSystemRuntimeMutex ()
+{
+ static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
+ return g_instances_mutex;
+}
+
+static SystemRuntimeInstances &
+GetSystemRuntimeInstances ()
+{
+ static SystemRuntimeInstances g_instances;
+ return g_instances;
+}
+
+bool
+PluginManager::RegisterPlugin
+(
+ const ConstString &name,
+ const char *description,
+ SystemRuntimeCreateInstance create_callback
+)
+{
+ if (create_callback)
+ {
+ SystemRuntimeInstance instance;
+ assert ((bool)name);
+ instance.name = name;
+ if (description && description[0])
+ instance.description = description;
+ instance.create_callback = create_callback;
+ Mutex::Locker locker (GetSystemRuntimeMutex ());
+ GetSystemRuntimeInstances ().push_back (instance);
+ }
+ return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (SystemRuntimeCreateInstance create_callback)
+{
+ if (create_callback)
+ {
+ Mutex::Locker locker (GetSystemRuntimeMutex ());
+ SystemRuntimeInstances &instances = GetSystemRuntimeInstances ();
+
+ SystemRuntimeInstances::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;
+}
+
+SystemRuntimeCreateInstance
+PluginManager::GetSystemRuntimeCreateCallbackAtIndex (uint32_t idx)
+{
+ Mutex::Locker locker (GetSystemRuntimeMutex ());
+ SystemRuntimeInstances &instances = GetSystemRuntimeInstances ();
+ if (idx < instances.size())
+ return instances[idx].create_callback;
+ return NULL;
+}
+
+SystemRuntimeCreateInstance
+PluginManager::GetSystemRuntimeCreateCallbackForPluginName (const ConstString &name)
+{
+ if (name)
+ {
+ Mutex::Locker locker (GetSystemRuntimeMutex ());
+ SystemRuntimeInstances &instances = GetSystemRuntimeInstances ();
+
+ SystemRuntimeInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (name == pos->name)
+ return pos->create_callback;
+ }
+ }
+ return NULL;
+}
+
+
#pragma mark ObjectFile
struct ObjectFileInstance
diff --git a/source/Core/SearchFilter.cpp b/source/Core/SearchFilter.cpp
index 54937c0afeca..64b5a838d3de 100644
--- a/source/Core/SearchFilter.cpp
+++ b/source/Core/SearchFilter.cpp
@@ -361,7 +361,7 @@ bool
SearchFilterByModule::ModulePasses (const FileSpec &spec)
{
// Do a full match only if "spec" has a directory
- const bool full_match = spec.GetDirectory();
+ const bool full_match = (bool)spec.GetDirectory();
return FileSpec::Equal(spec, m_module_spec, full_match);
}
@@ -409,7 +409,7 @@ SearchFilterByModule::Search (Searcher &searcher)
for (size_t i = 0; i < num_modules; i++)
{
Module* module = target_modules.GetModulePointerAtIndexUnlocked(i);
- const bool full_match = m_module_spec.GetDirectory();
+ const bool full_match = (bool)m_module_spec.GetDirectory();
if (FileSpec::Equal (m_module_spec, module->GetFileSpec(), full_match))
{
SymbolContext matchingContext(m_target_sp, module->shared_from_this());
diff --git a/source/Core/SourceManager.cpp b/source/Core/SourceManager.cpp
index 9f289348fd91..940034625c0a 100644
--- a/source/Core/SourceManager.cpp
+++ b/source/Core/SourceManager.cpp
@@ -567,15 +567,15 @@ SourceManager::File::CalculateLineOffsets (uint32_t line)
// Push a 1 at index zero to indicate the file has been completely indexed.
m_offsets.push_back(UINT32_MAX);
- register const char *s;
+ const char *s;
for (s = start; s < end; ++s)
{
- register char curr_ch = *s;
+ char curr_ch = *s;
if (is_newline_char (curr_ch))
{
if (s + 1 < end)
{
- register char next_ch = s[1];
+ char next_ch = s[1];
if (is_newline_char (next_ch))
{
if (curr_ch != next_ch)
diff --git a/source/Core/StreamGDBRemote.cpp b/source/Core/StreamGDBRemote.cpp
new file mode 100644
index 000000000000..46cb99ce98a5
--- /dev/null
+++ b/source/Core/StreamGDBRemote.cpp
@@ -0,0 +1,54 @@
+//===-- StreamGDBRemote.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/StreamGDBRemote.h"
+#include <stdio.h>
+
+using namespace lldb;
+using namespace lldb_private;
+
+StreamGDBRemote::StreamGDBRemote () :
+StreamString ()
+{
+}
+
+StreamGDBRemote::StreamGDBRemote(uint32_t flags, uint32_t addr_size, ByteOrder byte_order) :
+StreamString (flags, addr_size, byte_order)
+{
+}
+
+StreamGDBRemote::~StreamGDBRemote()
+{
+}
+
+
+int
+StreamGDBRemote::PutEscapedBytes (const void* s,
+ size_t src_len)
+{
+ int bytes_written = 0;
+ const uint8_t *src = (const uint8_t *)s;
+ bool binary_is_set = m_flags.Test(eBinary);
+ m_flags.Clear(eBinary);
+ while (src_len)
+ {
+ uint8_t byte = *src;
+ src++; src_len--;
+ if (byte == 0x23 || byte == 0x24 || byte == 0x7d || byte == 0x2a)
+ {
+ bytes_written += PutChar(0x7d);
+ byte ^= 0x20;
+ }
+ bytes_written += PutChar(byte);
+ };
+ if (binary_is_set)
+ m_flags.Set(eBinary);
+ return bytes_written;
+}
+
diff --git a/source/Core/Timer.cpp b/source/Core/Timer.cpp
index b1416bdaf62e..bbd990056ba0 100644
--- a/source/Core/Timer.cpp
+++ b/source/Core/Timer.cpp
@@ -14,6 +14,7 @@
#include "lldb/Core/Stream.h"
#include "lldb/Host/Mutex.h"
+#include "lldb/Host/Host.h"
#include <stdio.h>
@@ -26,7 +27,7 @@ uint32_t Timer::g_display_depth = 0;
FILE * Timer::g_file = NULL;
typedef std::vector<Timer *> TimerStack;
typedef std::map<const char *, uint64_t> TimerCategoryMap;
-static pthread_key_t g_key;
+static lldb::thread_key_t g_key;
static Mutex &
GetCategoryMutex()
@@ -46,11 +47,11 @@ GetCategoryMap()
static TimerStack *
GetTimerStackForCurrentThread ()
{
- void *timer_stack = ::pthread_getspecific (g_key);
+ void *timer_stack = Host::ThreadLocalStorageGet(g_key);
if (timer_stack == NULL)
{
- ::pthread_setspecific (g_key, new TimerStack);
- timer_stack = ::pthread_getspecific (g_key);
+ Host::ThreadLocalStorageSet(g_key, new TimerStack);
+ timer_stack = Host::ThreadLocalStorageGet(g_key);
}
return (TimerStack *)timer_stack;
}
@@ -71,8 +72,7 @@ void
Timer::Initialize ()
{
Timer::g_file = stdout;
- ::pthread_key_create (&g_key, ThreadSpecificCleanup);
-
+ g_key = Host::ThreadLocalStorageCreate(ThreadSpecificCleanup);
}
Timer::Timer (const char *category, const char *format, ...) :
diff --git a/source/Core/Value.cpp b/source/Core/Value.cpp
index 3fe75d3d4ce5..9dd72c7546bf 100644
--- a/source/Core/Value.cpp
+++ b/source/Core/Value.cpp
@@ -339,16 +339,30 @@ Value::GetValueAsData (ExecutionContext *exe_ctx,
break;
case eValueTypeScalar:
- data.SetByteOrder (lldb::endian::InlHostByteOrder());
- if (ast_type.IsValid())
- data.SetAddressByteSize (ast_type.GetPointerByteSize());
- else
- data.SetAddressByteSize(sizeof(void *));
- if (m_value.GetData (data))
- return error; // Success;
- error.SetErrorStringWithFormat("extracting data from value failed");
- break;
+ {
+ data.SetByteOrder (lldb::endian::InlHostByteOrder());
+ if (ast_type.IsValid())
+ data.SetAddressByteSize (ast_type.GetPointerByteSize());
+ else
+ data.SetAddressByteSize(sizeof(void *));
+ uint32_t limit_byte_size = UINT32_MAX;
+
+ if (ast_type.IsValid() && ast_type.IsScalarType())
+ {
+ uint64_t type_encoding_count = 0;
+ lldb::Encoding type_encoding = ast_type.GetEncoding(type_encoding_count);
+
+ if (type_encoding == eEncodingUint || type_encoding == eEncodingSint)
+ limit_byte_size = ast_type.GetByteSize();
+ }
+
+ if (m_value.GetData (data, limit_byte_size))
+ return error; // Success;
+
+ error.SetErrorStringWithFormat("extracting data from value failed");
+ break;
+ }
case eValueTypeLoadAddress:
if (exe_ctx == NULL)
{
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp
index a30cc1306c6b..d39d21a2a0bf 100644
--- a/source/Core/ValueObject.cpp
+++ b/source/Core/ValueObject.cpp
@@ -34,6 +34,7 @@
#include "lldb/Core/ValueObjectSyntheticFilter.h"
#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/Endian.h"
@@ -170,13 +171,12 @@ ValueObject::UpdateValueIfNeeded (bool update_format)
// we have an error or not
if (GetIsConstant())
{
- // if you were asked to update your formatters, but did not get a chance to do it
- // clear your own values (this serves the purpose of faking a stop-id for frozen
- // objects (which are regarded as constant, but could have changes behind their backs
- // because of the frozen-pointer depth limit)
- // TODO: decouple summary from value and then remove this code and only force-clear the summary
+ // if you are constant, things might still have changed behind your back
+ // (e.g. you are a frozen object and things have changed deeper than you cared to freeze-dry yourself)
+ // in this case, your value has not changed, but "computed" entries might have, so you might now have
+ // a different summary, or a different object description. clear these so we will recompute them
if (update_format && !did_change_formats)
- ClearUserVisibleData(eClearUserVisibleDataItemsSummary);
+ ClearUserVisibleData(eClearUserVisibleDataItemsSummary | eClearUserVisibleDataItemsDescription);
return m_error.Success();
}
@@ -245,7 +245,7 @@ ValueObject::UpdateFormatsIfNeeded()
if ( (m_last_format_mgr_revision != DataVisualization::GetCurrentRevision()))
{
- SetValueFormat(DataVisualization::ValueFormats::GetFormat (*this, eNoDynamicValues));
+ SetValueFormat(DataVisualization::GetFormat (*this, eNoDynamicValues));
SetSummaryFormat(DataVisualization::GetSummaryFormat (*this, GetDynamicValueType()));
#ifndef LLDB_DISABLE_PYTHON
SetSyntheticChildren(DataVisualization::GetSyntheticChildren (*this, GetDynamicValueType()));
@@ -272,6 +272,7 @@ ValueObject::SetNeedsUpdate ()
void
ValueObject::ClearDynamicTypeInformation ()
{
+ m_children_count_valid = false;
m_did_calculate_complete_objc_class_type = false;
m_last_format_mgr_revision = 0;
m_override_type = ClangASTType();
@@ -359,6 +360,12 @@ ValueObject::GetClangType ()
return MaybeCalculateCompleteType();
}
+TypeImpl
+ValueObject::GetTypeImpl ()
+{
+ return TypeImpl(GetClangType());
+}
+
DataExtractor &
ValueObject::GetDataExtractor ()
{
@@ -595,6 +602,86 @@ ValueObject::GetChildAtIndexPath (const std::vector< std::pair<size_t, bool> > &
return root;
}
+lldb::ValueObjectSP
+ValueObject::GetChildAtNamePath (const std::initializer_list<ConstString> &names,
+ ConstString* name_of_error)
+{
+ if (names.size() == 0)
+ return GetSP();
+ ValueObjectSP root(GetSP());
+ for (ConstString name : names)
+ {
+ root = root->GetChildMemberWithName(name, true);
+ if (!root)
+ {
+ if (name_of_error)
+ *name_of_error = name;
+ return root;
+ }
+ }
+ return root;
+}
+
+lldb::ValueObjectSP
+ValueObject::GetChildAtNamePath (const std::vector<ConstString> &names,
+ ConstString* name_of_error)
+{
+ if (names.size() == 0)
+ return GetSP();
+ ValueObjectSP root(GetSP());
+ for (ConstString name : names)
+ {
+ root = root->GetChildMemberWithName(name, true);
+ if (!root)
+ {
+ if (name_of_error)
+ *name_of_error = name;
+ return root;
+ }
+ }
+ return root;
+}
+
+lldb::ValueObjectSP
+ValueObject::GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names,
+ ConstString* name_of_error)
+{
+ if (names.size() == 0)
+ return GetSP();
+ ValueObjectSP root(GetSP());
+ for (std::pair<ConstString, bool> name : names)
+ {
+ root = root->GetChildMemberWithName(name.first, name.second);
+ if (!root)
+ {
+ if (name_of_error)
+ *name_of_error = name.first;
+ return root;
+ }
+ }
+ return root;
+}
+
+lldb::ValueObjectSP
+ValueObject::GetChildAtNamePath (const std::vector< std::pair<ConstString, bool> > &names,
+ ConstString* name_of_error)
+{
+ if (names.size() == 0)
+ return GetSP();
+ ValueObjectSP root(GetSP());
+ for (std::pair<ConstString, bool> name : names)
+ {
+ root = root->GetChildMemberWithName(name.first, name.second);
+ if (!root)
+ {
+ if (name_of_error)
+ *name_of_error = name.first;
+ return root;
+ }
+ }
+ return root;
+}
+
size_t
ValueObject::GetIndexOfChildWithName (const ConstString &name)
{
@@ -943,7 +1030,7 @@ ValueObject::GetPointeeData (DataExtractor& data,
{
heap_buf_ptr->SetByteSize(bytes);
size_t bytes_read = process->ReadMemory(addr + offset, heap_buf_ptr->GetBytes(), bytes, error);
- if (error.Success())
+ if (error.Success() || bytes_read > 0)
{
data.SetData(data_sp);
return bytes_read;
@@ -1455,6 +1542,27 @@ ValueObject::GetValueAsUnsigned (uint64_t fail_value, bool *success)
return fail_value;
}
+int64_t
+ValueObject::GetValueAsSigned (int64_t fail_value, bool *success)
+{
+ // If our byte size is zero this is an aggregate type that has children
+ if (!GetClangType().IsAggregateType())
+ {
+ Scalar scalar;
+ if (ResolveValue (scalar))
+ {
+ if (success)
+ *success = true;
+ return scalar.SLongLong(fail_value);
+ }
+ // fallthrough, otherwise...
+ }
+
+ if (success)
+ *success = false;
+ return fail_value;
+}
+
// if any more "special cases" are added to ValueObject::DumpPrintableRepresentation() please keep
// this call up to date by returning true for your new special cases. We will eventually move
// to checking this call result before trying to display special cases
@@ -2211,7 +2319,7 @@ ValueObject::CalculateSyntheticValue (bool use_synthetic)
return;
TargetSP target_sp(GetTargetSP());
- if (target_sp && (target_sp->GetEnableSyntheticValue() == false || target_sp->GetSuppressSyntheticValue() == true))
+ if (target_sp && target_sp->GetEnableSyntheticValue() == false)
{
m_synthetic_value = NULL;
return;
@@ -3342,329 +3450,39 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr,
}
}
-static void
-DumpValueObject_Impl (Stream &s,
- ValueObject *valobj,
- const ValueObject::DumpValueObjectOptions& options,
- uint32_t ptr_depth,
- uint32_t curr_depth)
-{
- if (valobj)
- {
- bool update_success = valobj->UpdateValueIfNeeded (true);
-
- const char *root_valobj_name =
- options.m_root_valobj_name.empty() ?
- valobj->GetName().AsCString() :
- options.m_root_valobj_name.c_str();
-
- if (update_success && options.m_use_dynamic != eNoDynamicValues)
- {
- ValueObject *dynamic_value = valobj->GetDynamicValue(options.m_use_dynamic).get();
- if (dynamic_value)
- valobj = dynamic_value;
- }
-
- ClangASTType clang_type = valobj->GetClangType();
- const Flags type_flags (clang_type.GetTypeInfo ());
- const char *err_cstr = NULL;
- const bool has_children = type_flags.Test (ClangASTType::eTypeHasChildren);
- const bool has_value = type_flags.Test (ClangASTType::eTypeHasValue);
-
- const bool print_valobj = options.m_flat_output == false || has_value;
-
- if (print_valobj)
- {
- if (options.m_show_location)
- {
- s.Printf("%s: ", valobj->GetLocationAsCString());
- }
-
- s.Indent();
-
- bool show_type = true;
- // if we are at the root-level and been asked to hide the root's type, then hide it
- if (curr_depth == 0 && options.m_hide_root_type)
- show_type = false;
- else
- // otherwise decide according to the usual rules (asked to show types - always at the root level)
- show_type = options.m_show_types || (curr_depth == 0 && !options.m_flat_output);
-
- if (show_type)
- {
- // Some ValueObjects don't have types (like registers sets). Only print
- // the type if there is one to print
- ConstString qualified_type_name(valobj->GetQualifiedTypeName());
- if (qualified_type_name)
- s.Printf("(%s) ", qualified_type_name.GetCString());
- }
-
- if (options.m_flat_output)
- {
- // If we are showing types, also qualify the C++ base classes
- const bool qualify_cxx_base_classes = options.m_show_types;
- if (!options.m_hide_name)
- {
- valobj->GetExpressionPath(s, qualify_cxx_base_classes);
- s.PutCString(" =");
- }
- }
- else if (!options.m_hide_name)
- {
- const char *name_cstr = root_valobj_name ? root_valobj_name : valobj->GetName().AsCString("");
- s.Printf ("%s =", name_cstr);
- }
-
- if (!options.m_scope_already_checked && !valobj->IsInScope())
- {
- err_cstr = "out of scope";
- }
- }
-
- std::string summary_str;
- std::string value_str;
- const char *val_cstr = NULL;
- const char *sum_cstr = NULL;
- TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : valobj->GetSummaryFormat().get();
-
- if (options.m_omit_summary_depth > 0)
- entry = NULL;
-
- bool is_nil = valobj->IsObjCNil();
-
- if (err_cstr == NULL)
- {
- if (options.m_format != eFormatDefault && options.m_format != valobj->GetFormat())
- {
- valobj->GetValueAsCString(options.m_format,
- value_str);
- }
- else
- {
- val_cstr = valobj->GetValueAsCString();
- if (val_cstr)
- value_str = val_cstr;
- }
- err_cstr = valobj->GetError().AsCString();
- }
-
- if (err_cstr)
- {
- s.Printf (" <%s>\n", err_cstr);
- }
- else
- {
- const bool is_ref = type_flags.Test (ClangASTType::eTypeIsReference);
- if (print_valobj)
- {
- if (is_nil)
- sum_cstr = "nil";
- else if (options.m_omit_summary_depth == 0)
- {
- if (options.m_summary_sp)
- {
- valobj->GetSummaryAsCString(entry, summary_str);
- sum_cstr = summary_str.c_str();
- }
- else
- sum_cstr = valobj->GetSummaryAsCString();
- }
-
- // Make sure we have a value and make sure the summary didn't
- // specify that the value should not be printed - and do not print
- // the value if this thing is nil
- // (but show the value if the user passes a format explicitly)
- if (!is_nil && !value_str.empty() && (entry == NULL || (entry->DoesPrintValue() || options.m_format != eFormatDefault) || sum_cstr == NULL) && !options.m_hide_value)
- s.Printf(" %s", value_str.c_str());
-
- if (sum_cstr)
- s.Printf(" %s", sum_cstr);
-
- // let's avoid the overly verbose no description error for a nil thing
- if (options.m_use_objc && !is_nil)
- {
- if (!options.m_hide_value || !options.m_hide_name)
- s.Printf(" ");
- const char *object_desc = valobj->GetObjectDescription();
- if (object_desc)
- s.Printf("%s\n", object_desc);
- else
- s.Printf ("[no Objective-C description available]\n");
- return;
- }
- }
-
- if (curr_depth < options.m_max_depth)
- {
- // We will show children for all concrete types. We won't show
- // pointer contents unless a pointer depth has been specified.
- // We won't reference contents unless the reference is the
- // root object (depth of zero).
- bool print_children = true;
-
- // Use a new temporary pointer depth in case we override the
- // current pointer depth below...
- uint32_t curr_ptr_depth = ptr_depth;
-
- const bool is_ptr = type_flags.Test (ClangASTType::eTypeIsPointer);
- if (is_ptr || is_ref)
- {
- // We have a pointer or reference whose value is an address.
- // Make sure that address is not NULL
- AddressType ptr_address_type;
- if (valobj->GetPointerValue (&ptr_address_type) == 0)
- print_children = false;
-
- else if (is_ref && curr_depth == 0)
- {
- // If this is the root object (depth is zero) that we are showing
- // and it is a reference, and no pointer depth has been supplied
- // print out what it references. Don't do this at deeper depths
- // otherwise we can end up with infinite recursion...
- curr_ptr_depth = 1;
- }
-
- if (curr_ptr_depth == 0)
- print_children = false;
- }
-
- if (print_children && (!entry || entry->DoesPrintChildren() || !sum_cstr))
- {
- ValueObjectSP synth_valobj_sp = valobj->GetSyntheticValue (options.m_use_synthetic);
- ValueObject* synth_valobj = (synth_valobj_sp ? synth_valobj_sp.get() : valobj);
-
- size_t num_children = synth_valobj->GetNumChildren();
- bool print_dotdotdot = false;
- if (num_children)
- {
- if (options.m_flat_output)
- {
- if (print_valobj)
- s.EOL();
- }
- else
- {
- if (print_valobj)
- s.PutCString(is_ref ? ": {\n" : " {\n");
- s.IndentMore();
- }
-
- const size_t max_num_children = valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
-
- if (num_children > max_num_children && !options.m_ignore_cap)
- {
- num_children = max_num_children;
- print_dotdotdot = true;
- }
-
- ValueObject::DumpValueObjectOptions child_options(options);
- child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName();
- child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value)
- .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0);
- for (size_t idx=0; idx<num_children; ++idx)
- {
- ValueObjectSP child_sp(synth_valobj->GetChildAtIndex(idx, true));
- if (child_sp.get())
- {
- DumpValueObject_Impl (s,
- child_sp.get(),
- child_options,
- (is_ptr || is_ref) ? curr_ptr_depth - 1 : curr_ptr_depth,
- curr_depth + 1);
- }
- }
-
- if (!options.m_flat_output)
- {
- if (print_dotdotdot)
- {
- ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
- Target *target = exe_ctx.GetTargetPtr();
- if (target)
- target->GetDebugger().GetCommandInterpreter().ChildrenTruncated();
- s.Indent("...\n");
- }
- s.IndentLess();
- s.Indent("}\n");
- }
- }
- else if (has_children)
- {
- // Aggregate, no children...
- if (print_valobj)
- s.PutCString(" {}\n");
- }
- else
- {
- if (print_valobj)
- s.EOL();
- }
-
- }
- else
- {
- s.EOL();
- }
- }
- else
- {
- if (has_children && print_valobj)
- {
- s.PutCString("{...}\n");
- }
- }
- }
- }
-}
-
void
-ValueObject::LogValueObject (Log *log,
- ValueObject *valobj)
+ValueObject::LogValueObject (Log *log)
{
- if (log && valobj)
- return LogValueObject (log, valobj, DumpValueObjectOptions::DefaultOptions());
+ if (log)
+ return LogValueObject (log, DumpValueObjectOptions::DefaultOptions());
}
void
-ValueObject::LogValueObject (Log *log,
- ValueObject *valobj,
- const DumpValueObjectOptions& options)
+ValueObject::LogValueObject (Log *log, const DumpValueObjectOptions& options)
{
- if (log && valobj)
+ if (log)
{
StreamString s;
- ValueObject::DumpValueObject (s, valobj, options);
+ Dump (s, options);
if (s.GetSize())
log->PutCString(s.GetData());
}
}
void
-ValueObject::DumpValueObject (Stream &s,
- ValueObject *valobj)
+ValueObject::Dump (Stream &s)
{
- if (!valobj)
- return;
-
- DumpValueObject_Impl(s,
- valobj,
- DumpValueObjectOptions::DefaultOptions(),
- 0,
- 0);
+ ValueObjectPrinter printer(this,&s,DumpValueObjectOptions::DefaultOptions());
+ printer.PrintValueObject();
}
void
-ValueObject::DumpValueObject (Stream &s,
- ValueObject *valobj,
- const DumpValueObjectOptions& options)
+ValueObject::Dump (Stream &s,
+ const DumpValueObjectOptions& options)
{
- DumpValueObject_Impl(s,
- valobj,
- options,
- options.m_max_ptr_depth, // max pointer depth allowed, we will go down from here
- 0 // current object depth is 0 since we are just starting
- );
+ ValueObjectPrinter printer(this,&s,options);
+ printer.PrintValueObject();
}
ValueObjectSP
diff --git a/source/Core/ValueObjectDynamicValue.cpp b/source/Core/ValueObjectDynamicValue.cpp
index 977cc4cd3132..47e781e71156 100644
--- a/source/Core/ValueObjectDynamicValue.cpp
+++ b/source/Core/ValueObjectDynamicValue.cpp
@@ -52,10 +52,15 @@ ValueObjectDynamicValue::~ValueObjectDynamicValue()
ClangASTType
ValueObjectDynamicValue::GetClangTypeImpl ()
{
- if (m_dynamic_type_info.HasTypeSP())
- return m_value.GetClangType();
- else
- return m_parent->GetClangType();
+ const bool success = UpdateValueIfNeeded(false);
+ if (success)
+ {
+ if (m_dynamic_type_info.HasType())
+ return m_value.GetClangType();
+ else
+ return m_parent->GetClangType();
+ }
+ return m_parent->GetClangType();
}
ConstString
@@ -64,24 +69,35 @@ ValueObjectDynamicValue::GetTypeName()
const bool success = UpdateValueIfNeeded(false);
if (success)
{
- if (m_dynamic_type_info.HasTypeSP())
- return GetClangType().GetConstTypeName();
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();
}
+TypeImpl
+ValueObjectDynamicValue::GetTypeImpl ()
+{
+ const bool success = UpdateValueIfNeeded(false);
+ if (success && m_type_impl.IsValid())
+ {
+ return m_type_impl;
+ }
+ return m_parent->GetTypeImpl();
+}
+
ConstString
ValueObjectDynamicValue::GetQualifiedTypeName()
{
const bool success = UpdateValueIfNeeded(false);
if (success)
{
- if (m_dynamic_type_info.HasTypeSP())
- return GetClangType().GetConstQualifiedTypeName ();
if (m_dynamic_type_info.HasName())
return m_dynamic_type_info.GetName();
+ if (m_dynamic_type_info.HasType())
+ return GetClangType().GetConstQualifiedTypeName ();
}
return m_parent->GetTypeName();
}
@@ -90,7 +106,7 @@ size_t
ValueObjectDynamicValue::CalculateNumChildren()
{
const bool success = UpdateValueIfNeeded(false);
- if (success && m_dynamic_type_info.HasTypeSP())
+ if (success && m_dynamic_type_info.HasType())
return GetClangType().GetNumChildren (true);
else
return m_parent->GetNumChildren();
@@ -100,7 +116,7 @@ uint64_t
ValueObjectDynamicValue::GetByteSize()
{
const bool success = UpdateValueIfNeeded(false);
- if (success && m_dynamic_type_info.HasTypeSP())
+ if (success && m_dynamic_type_info.HasType())
return m_value.GetValueByteSize(NULL);
else
return m_parent->GetByteSize();
@@ -112,6 +128,40 @@ ValueObjectDynamicValue::GetValueType() const
return m_parent->GetValueType();
}
+
+static TypeAndOrName
+FixupTypeAndOrName (const TypeAndOrName& type_andor_name,
+ ValueObject& parent)
+{
+ TypeAndOrName ret(type_andor_name);
+ if (type_andor_name.HasType())
+ {
+ // The type will always be the type of the dynamic object. If our parent's type was a pointer,
+ // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type
+ // should be okay...
+ ClangASTType orig_type = type_andor_name.GetClangASTType();
+ ClangASTType corrected_type = orig_type;
+ if (parent.IsPointerType())
+ corrected_type = orig_type.GetPointerType ();
+ else if (parent.IsPointerOrReferenceType())
+ corrected_type = orig_type.GetLValueReferenceType ();
+ ret.SetClangASTType(corrected_type);
+ }
+ else /*if (m_dynamic_type_info.HasName())*/
+ {
+ // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
+ std::string corrected_name (type_andor_name.GetName().GetCString());
+ if (parent.IsPointerType())
+ corrected_name.append(" *");
+ else if (parent.IsPointerOrReferenceType())
+ corrected_name.append(" &");
+ // the parent type should be a correctly pointer'ed or referenc'ed type
+ ret.SetClangASTType(parent.GetClangType());
+ ret.SetName(corrected_name.c_str());
+ }
+ return ret;
+}
+
bool
ValueObjectDynamicValue::UpdateValue ()
{
@@ -176,6 +226,31 @@ ValueObjectDynamicValue::UpdateValue ()
// don't...
m_update_point.SetUpdated();
+
+ if (found_dynamic_type)
+ {
+ if (class_type_or_name.HasType())
+ {
+ // TypeSP are always generated from debug info
+ if (!class_type_or_name.HasTypeSP() && class_type_or_name.GetClangASTType().IsRuntimeGeneratedType())
+ {
+ m_type_impl = TypeImpl(m_parent->GetClangType(),FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType());
+ class_type_or_name.SetClangASTType(ClangASTType());
+ }
+ else
+ {
+ m_type_impl = TypeImpl(FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType());
+ }
+ }
+ else
+ {
+ m_type_impl.Clear();
+ }
+ }
+ else
+ {
+ 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?
@@ -224,33 +299,10 @@ ValueObjectDynamicValue::UpdateValue ()
m_value.GetScalar() = load_address;
}
- ClangASTType corrected_type;
- if (m_dynamic_type_info.HasTypeSP())
- {
- // The type will always be the type of the dynamic object. If our parent's type was a pointer,
- // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type
- // should be okay...
- ClangASTType orig_type = m_dynamic_type_info.GetTypeSP()->GetClangForwardType();
- corrected_type = orig_type;
- if (m_parent->IsPointerType())
- corrected_type = orig_type.GetPointerType ();
- else if (m_parent->IsPointerOrReferenceType())
- corrected_type = orig_type.GetLValueReferenceType ();
- }
- else /*if (m_dynamic_type_info.HasName())*/
- {
- // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
- std::string type_name_buf (m_dynamic_type_info.GetName().GetCString());
- if (m_parent->IsPointerType())
- type_name_buf.append(" *");
- else if (m_parent->IsPointerOrReferenceType())
- type_name_buf.append(" &");
- corrected_type = m_parent->GetClangType();
- m_dynamic_type_info.SetName(type_name_buf.c_str());
- }
+ m_dynamic_type_info = FixupTypeAndOrName(m_dynamic_type_info, *m_parent);
//m_value.SetContext (Value::eContextTypeClangType, corrected_type);
- m_value.SetClangType (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...
diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp
index 522ca082a691..5767466f509d 100644
--- a/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/source/Core/ValueObjectSyntheticFilter.cpp
@@ -30,19 +30,19 @@ public:
size_t
CalculateNumChildren()
{
- return 0;
+ return m_backend.GetNumChildren();
}
lldb::ValueObjectSP
GetChildAtIndex (size_t idx)
{
- return lldb::ValueObjectSP();
+ return m_backend.GetChildAtIndex(idx, true);
}
size_t
GetIndexOfChildWithName (const ConstString &name)
{
- return UINT32_MAX;
+ return m_backend.GetIndexOfChildWithName(name);
}
bool
diff --git a/source/Core/ValueObjectVariable.cpp b/source/Core/ValueObjectVariable.cpp
index 38c0d91324ad..3d8b07a36948 100644
--- a/source/Core/ValueObjectVariable.cpp
+++ b/source/Core/ValueObjectVariable.cpp
@@ -156,6 +156,10 @@ ValueObjectVariable::UpdateValue ()
{
m_resolved_value = m_value;
m_value.SetContext(Value::eContextTypeVariable, variable);
+
+ ClangASTType clang_type = GetClangType();
+ if (clang_type.IsValid())
+ m_value.SetClangType(clang_type);
Value::ValueType value_type = m_value.GetValueType();
diff --git a/source/DataFormatters/CXXFormatterFunctions.cpp b/source/DataFormatters/CXXFormatterFunctions.cpp
index fba92170d832..e00413556cc9 100644
--- a/source/DataFormatters/CXXFormatterFunctions.cpp
+++ b/source/DataFormatters/CXXFormatterFunctions.cpp
@@ -1003,11 +1003,11 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream&
if (!has_null && has_explicit_length && !is_special)
{
lldb::addr_t explicit_length_offset = 2*ptr_size;
- if (is_mutable and not is_inline)
+ if (is_mutable && !is_inline)
explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
else if (is_inline)
explicit_length = explicit_length + 0; // inline1.length;
- else if (not is_inline and not is_mutable)
+ else if (!is_inline && !is_mutable)
explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
else
explicit_length_offset = 0;
@@ -1039,7 +1039,7 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream&
location = process_sp->ReadPointerFromMemory(location, error);
if (error.Fail())
return false;
- if (has_explicit_length and is_unicode)
+ if (has_explicit_length && is_unicode)
{
ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
options.SetConversionFunction(ConvertUTF16toUTF8);
@@ -1237,6 +1237,7 @@ lldb_private::formatters::GetOSXEpoch ()
static time_t epoch = 0;
if (!epoch)
{
+#ifndef _WIN32
tzset();
tm tm_epoch;
tm_epoch.tm_sec = 0;
@@ -1249,6 +1250,7 @@ lldb_private::formatters::GetOSXEpoch ()
tm_epoch.tm_gmtoff = 0;
tm_epoch.tm_zone = NULL;
epoch = timegm(&tm_epoch);
+#endif
}
return epoch;
}
diff --git a/source/DataFormatters/DataVisualization.cpp b/source/DataFormatters/DataVisualization.cpp
index c1ef359049b6..48d3517750aa 100644
--- a/source/DataFormatters/DataVisualization.cpp
+++ b/source/DataFormatters/DataVisualization.cpp
@@ -40,67 +40,26 @@ DataVisualization::GetCurrentRevision ()
return GetFormatManager().GetCurrentRevision();
}
-lldb::TypeFormatImplSP
-DataVisualization::ValueFormats::GetFormat (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
-{
- lldb::TypeFormatImplSP entry;
- GetFormatManager().GetValueNavigator().Get(valobj, entry, use_dynamic);
- return entry;
-}
-
-lldb::TypeFormatImplSP
-DataVisualization::ValueFormats::GetFormat (const ConstString &type)
-{
- lldb::TypeFormatImplSP entry;
- GetFormatManager().GetValueNavigator().Get(type, entry);
- return entry;
-}
-
-void
-DataVisualization::ValueFormats::Add (const ConstString &type, const lldb::TypeFormatImplSP &entry)
-{
- GetFormatManager().GetValueNavigator().Add(FormatManager::GetValidTypeName(type),entry);
-}
-
bool
-DataVisualization::ValueFormats::Delete (const ConstString &type)
+DataVisualization::ShouldPrintAsOneLiner (ValueObject& valobj)
{
- return GetFormatManager().GetValueNavigator().Delete(type);
+ return GetFormatManager().ShouldPrintAsOneLiner(valobj);
}
-void
-DataVisualization::ValueFormats::Clear ()
-{
- GetFormatManager().GetValueNavigator().Clear();
-}
-
-void
-DataVisualization::ValueFormats::LoopThrough (TypeFormatImpl::ValueCallback callback, void* callback_baton)
-{
- GetFormatManager().GetValueNavigator().LoopThrough(callback, callback_baton);
-}
-
-size_t
-DataVisualization::ValueFormats::GetCount ()
-{
- return GetFormatManager().GetValueNavigator().GetCount();
-}
-
-lldb::TypeNameSpecifierImplSP
-DataVisualization::ValueFormats::GetTypeNameSpecifierForFormatAtIndex (size_t index)
+lldb::TypeFormatImplSP
+DataVisualization::GetFormat (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
{
- return GetFormatManager().GetValueNavigator().GetTypeNameSpecifierAtIndex(index);
+ return GetFormatManager().GetFormat(valobj, use_dynamic);
}
lldb::TypeFormatImplSP
-DataVisualization::ValueFormats::GetFormatAtIndex (size_t index)
+DataVisualization::GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp)
{
- return GetFormatManager().GetValueNavigator().GetAtIndex(index);
+ return GetFormatManager().GetFormatForType(type_sp);
}
lldb::TypeSummaryImplSP
-DataVisualization::GetSummaryFormat (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+DataVisualization::GetSummaryFormat (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
{
return GetFormatManager().GetSummaryFormat(valobj, use_dynamic);
}
diff --git a/source/DataFormatters/FormatCache.cpp b/source/DataFormatters/FormatCache.cpp
index af7b1c386c32..3721f182f91e 100644
--- a/source/DataFormatters/FormatCache.cpp
+++ b/source/DataFormatters/FormatCache.cpp
@@ -22,33 +22,55 @@ using namespace lldb;
using namespace lldb_private;
FormatCache::Entry::Entry () :
+m_format_cached(false),
m_summary_cached(false),
m_synthetic_cached(false),
+m_format_sp(),
m_summary_sp(),
m_synthetic_sp()
{}
+FormatCache::Entry::Entry (lldb::TypeFormatImplSP format_sp) :
+m_summary_cached(false),
+m_synthetic_cached(false),
+m_summary_sp(),
+m_synthetic_sp()
+{
+ SetFormat (format_sp);
+}
+
FormatCache::Entry::Entry (lldb::TypeSummaryImplSP summary_sp) :
+m_format_cached(false),
m_synthetic_cached(false),
+m_format_sp(),
m_synthetic_sp()
{
SetSummary (summary_sp);
}
FormatCache::Entry::Entry (lldb::SyntheticChildrenSP synthetic_sp) :
+m_format_cached(false),
m_summary_cached(false),
+m_format_sp(),
m_summary_sp()
{
SetSynthetic (synthetic_sp);
}
-FormatCache::Entry::Entry (lldb::TypeSummaryImplSP summary_sp,lldb::SyntheticChildrenSP synthetic_sp)
+FormatCache::Entry::Entry (lldb::TypeFormatImplSP format_sp, lldb::TypeSummaryImplSP summary_sp, lldb::SyntheticChildrenSP synthetic_sp)
{
+ SetFormat (format_sp);
SetSummary (summary_sp);
SetSynthetic (synthetic_sp);
}
bool
+FormatCache::Entry::IsFormatCached ()
+{
+ return m_format_cached;
+}
+
+bool
FormatCache::Entry::IsSummaryCached ()
{
return m_summary_cached;
@@ -60,6 +82,12 @@ FormatCache::Entry::IsSyntheticCached ()
return m_synthetic_cached;
}
+lldb::TypeFormatImplSP
+FormatCache::Entry::GetFormat ()
+{
+ return m_format_sp;
+}
+
lldb::TypeSummaryImplSP
FormatCache::Entry::GetSummary ()
{
@@ -73,6 +101,13 @@ FormatCache::Entry::GetSynthetic ()
}
void
+FormatCache::Entry::SetFormat (lldb::TypeFormatImplSP format_sp)
+{
+ m_format_cached = true;
+ m_format_sp = format_sp;
+}
+
+void
FormatCache::Entry::SetSummary (lldb::TypeSummaryImplSP summary_sp)
{
m_summary_cached = true;
@@ -107,6 +142,26 @@ FormatCache::GetEntry (const ConstString& type)
}
bool
+FormatCache::GetFormat (const ConstString& type,lldb::TypeFormatImplSP& format_sp)
+{
+ Mutex::Locker lock(m_mutex);
+ auto entry = GetEntry(type);
+ if (entry.IsSummaryCached())
+ {
+#ifdef LLDB_CONFIGURATION_DEBUG
+ m_cache_hits++;
+#endif
+ format_sp = entry.GetFormat();
+ return true;
+ }
+#ifdef LLDB_CONFIGURATION_DEBUG
+ m_cache_misses++;
+#endif
+ format_sp.reset();
+ return false;
+}
+
+bool
FormatCache::GetSummary (const ConstString& type,lldb::TypeSummaryImplSP& summary_sp)
{
Mutex::Locker lock(m_mutex);
@@ -147,6 +202,13 @@ FormatCache::GetSynthetic (const ConstString& type,lldb::SyntheticChildrenSP& sy
}
void
+FormatCache::SetFormat (const ConstString& type,lldb::TypeFormatImplSP& format_sp)
+{
+ Mutex::Locker lock(m_mutex);
+ GetEntry(type).SetFormat(format_sp);
+}
+
+void
FormatCache::SetSummary (const ConstString& type,lldb::TypeSummaryImplSP& summary_sp)
{
Mutex::Locker lock(m_mutex);
diff --git a/source/DataFormatters/FormatManager.cpp b/source/DataFormatters/FormatManager.cpp
index eeae8bc9a19d..b4c4628b48a2 100644
--- a/source/DataFormatters/FormatManager.cpp
+++ b/source/DataFormatters/FormatManager.cpp
@@ -163,6 +163,32 @@ FormatManager::GetFormatAsCString (Format format)
return NULL;
}
+lldb::TypeFormatImplSP
+FormatManager::GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp)
+{
+ if (!type_sp)
+ return lldb::TypeFormatImplSP();
+ lldb::TypeFormatImplSP format_chosen_sp;
+ uint32_t num_categories = m_categories_map.GetCount();
+ lldb::TypeCategoryImplSP category_sp;
+ uint32_t prio_category = UINT32_MAX;
+ for (uint32_t category_id = 0;
+ category_id < num_categories;
+ category_id++)
+ {
+ category_sp = GetCategoryAtIndex(category_id);
+ if (category_sp->IsEnabled() == false)
+ continue;
+ lldb::TypeFormatImplSP format_current_sp = category_sp->GetFormatForType(type_sp);
+ if (format_current_sp && (format_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition())))
+ {
+ prio_category = category_sp->GetEnabledPosition();
+ format_chosen_sp = format_current_sp;
+ }
+ }
+ return format_chosen_sp;
+}
+
lldb::TypeSummaryImplSP
FormatManager::GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp)
{
@@ -305,6 +331,66 @@ FormatManager::GetSingleItemFormat(lldb::Format vector_format)
}
}
+bool
+FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj)
+{
+ // if settings say no oneline whatsoever
+ if (valobj.GetTargetSP().get() && valobj.GetTargetSP()->GetDebugger().GetAutoOneLineSummaries() == false)
+ return false; // then don't oneline
+
+ // if this object has a summary, don't try to do anything special to it
+ // if the user wants one-liner, they can ask for it in summary :)
+ if (valobj.GetSummaryFormat().get() != nullptr)
+ return false;
+
+ // no children, no party
+ if (valobj.GetNumChildren() == 0)
+ return false;
+
+ size_t total_children_name_len = 0;
+
+ for (size_t idx = 0;
+ idx < valobj.GetNumChildren();
+ idx++)
+ {
+ ValueObjectSP child_sp(valobj.GetChildAtIndex(idx, true));
+ // something is wrong here - bail out
+ if (!child_sp)
+ return false;
+ // if we decided to define synthetic children for a type, we probably care enough
+ // to show them, but avoid nesting children in children
+ if (child_sp->GetSyntheticChildren().get() != nullptr)
+ return false;
+
+ total_children_name_len += child_sp->GetName().GetLength();
+
+ // 50 itself is a "randomly" chosen number - the idea is that
+ // overly long structs should not get this treatment
+ // FIXME: maybe make this a user-tweakable setting?
+ if (total_children_name_len > 50)
+ return false;
+
+ // if a summary is there..
+ if (child_sp->GetSummaryFormat())
+ {
+ // and it wants children, then bail out
+ if (child_sp->GetSummaryFormat()->DoesPrintChildren())
+ return false;
+ }
+
+ // if this child has children..
+ if (child_sp->GetNumChildren())
+ {
+ // ...and no summary...
+ // (if it had a summary and the summary wanted children, we would have bailed out anyway
+ // so this only makes us bail out if this has no summary and we would then print children)
+ if (!child_sp->GetSummaryFormat())
+ return false; // then bail out
+ }
+ }
+ return true;
+}
+
ConstString
FormatManager::GetValidTypeName (const ConstString& type)
{
@@ -334,6 +420,62 @@ GetTypeForCache (ValueObject& valobj,
return ConstString();
}
+static lldb::TypeFormatImplSP
+GetHardcodedFormat (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
+{
+ return lldb::TypeFormatImplSP();
+}
+
+lldb::TypeFormatImplSP
+FormatManager::GetFormat (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
+{
+ TypeFormatImplSP retval;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ ConstString valobj_type(GetTypeForCache(valobj, use_dynamic));
+ if (valobj_type)
+ {
+ if (log)
+ log->Printf("\n\n[FormatManager::GetFormat] Looking into cache for type %s", valobj_type.AsCString("<invalid>"));
+ if (m_format_cache.GetFormat(valobj_type,retval))
+ {
+ if (log)
+ {
+ log->Printf("[FormatManager::GetFormat] Cache search success. Returning.");
+ if (log->GetDebug())
+ log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
+ }
+ return retval;
+ }
+ if (log)
+ log->Printf("[FormatManager::GetFormat] Cache search failed. Going normal route");
+ }
+ retval = m_categories_map.GetFormat(valobj, use_dynamic);
+ if (!retval)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded a chance.");
+ retval = GetHardcodedFormat(valobj, use_dynamic);
+ }
+ if (valobj_type)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetFormat] Caching %p for type %s",retval.get(),valobj_type.AsCString("<invalid>"));
+ m_format_cache.SetFormat(valobj_type,retval);
+ }
+ if (log && log->GetDebug())
+ log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
+ return retval;
+}
+
+static lldb::TypeSummaryImplSP
+GetHardcodedSummaryFormat (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
+{
+ return lldb::TypeSummaryImplSP();
+}
+
lldb::TypeSummaryImplSP
FormatManager::GetSummaryFormat (ValueObject& valobj,
lldb::DynamicValueType use_dynamic)
@@ -359,6 +501,12 @@ FormatManager::GetSummaryFormat (ValueObject& valobj,
log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. Going normal route");
}
retval = m_categories_map.GetSummaryFormat(valobj, use_dynamic);
+ if (!retval)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving hardcoded a chance.");
+ retval = GetHardcodedSummaryFormat(valobj, use_dynamic);
+ }
if (valobj_type)
{
if (log)
@@ -371,6 +519,13 @@ FormatManager::GetSummaryFormat (ValueObject& valobj,
}
#ifndef LLDB_DISABLE_PYTHON
+static lldb::SyntheticChildrenSP
+GetHardcodedSyntheticChildren (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
+{
+ return lldb::SyntheticChildrenSP();
+}
+
lldb::SyntheticChildrenSP
FormatManager::GetSyntheticChildren (ValueObject& valobj,
lldb::DynamicValueType use_dynamic)
@@ -396,6 +551,12 @@ FormatManager::GetSyntheticChildren (ValueObject& valobj,
log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. Going normal route");
}
retval = m_categories_map.GetSyntheticChildren(valobj, use_dynamic);
+ if (!retval)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving hardcoded a chance.");
+ retval = GetHardcodedSyntheticChildren(valobj, use_dynamic);
+ }
if (valobj_type)
{
if (log)
@@ -410,7 +571,6 @@ FormatManager::GetSyntheticChildren (ValueObject& valobj,
FormatManager::FormatManager() :
m_format_cache(),
- m_value_nav("format",this),
m_named_summaries_map(this),
m_last_revision(0),
m_categories_map(this),
@@ -442,6 +602,22 @@ FormatManager::FormatManager() :
}
static void
+AddFormat (TypeCategoryImpl::SharedPointer category_sp,
+ lldb::Format format,
+ ConstString type_name,
+ TypeFormatImpl::Flags flags,
+ bool regex = false)
+{
+ lldb::TypeFormatImplSP format_sp(new TypeFormatImpl(format, flags));
+
+ if (regex)
+ category_sp->GetRegexValueNavigator()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),format_sp);
+ else
+ category_sp->GetValueNavigator()->Add(type_name, format_sp);
+}
+
+
+static void
AddStringSummary(TypeCategoryImpl::SharedPointer category_sp,
const char* string,
ConstString type_name,
@@ -632,7 +808,8 @@ FormatManager::LoadLibcxxFormatters()
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);
-
+ AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_synth_flags, true);
+
libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")),
SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
"lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
@@ -650,6 +827,7 @@ FormatManager::LoadLibcxxFormatters()
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);
+ AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::unordered containers summary provider", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true);
stl_summary_flags.SetSkipPointers(true);
AddStringSummary(libcxx_category_sp, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})}", ConstString("^std::__1::shared_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
@@ -694,7 +872,7 @@ FormatManager::LoadSystemFormatters()
sys_category_sp->GetSummaryNavigator()->Add(ConstString("char *"), string_format);
sys_category_sp->GetSummaryNavigator()->Add(ConstString("unsigned char *"), string_format);
sys_category_sp->GetRegexSummaryNavigator()->Add(any_size_char_arr, string_array_format);
-
+
lldb::TypeSummaryImplSP ostype_summary(new StringSummaryFormat(TypeSummaryImpl::Flags().SetCascades(false)
.SetSkipPointers(true)
.SetSkipReferences(true)
@@ -731,6 +909,11 @@ FormatManager::LoadSystemFormatters()
AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16SummaryProvider, "unichar summary provider", ConstString("unichar"), widechar_flags);
+ TypeFormatImpl::Flags fourchar_flags;
+ fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences(true);
+
+ AddFormat(sys_category_sp, lldb::eFormatOSType, ConstString("FourCharCode"), fourchar_flags);
+
#endif
}
@@ -879,22 +1062,22 @@ FormatManager::LoadObjCFormatters()
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFMutableArrayRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFMutableArrayRef"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("NSDictionary"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("NSMutableDictionary"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSCFDictionary"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryI"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryM"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFDictionaryRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFMutableDictionaryRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFDictionaryRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFMutableDictionaryRef"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSSet summary", ConstString("NSSet"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFSetRef summary", ConstString("CFSetRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFSetRef summary", ConstString("CFSetRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSSetI summary", ConstString("__NSSetI"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSSetM summary", ConstString("__NSSetM"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags);
@@ -911,16 +1094,16 @@ FormatManager::LoadObjCFormatters()
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayI"), ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSArray"), ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSMutableArray"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSCFArray"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFMutableArrayRef"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFArrayRef"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSCFArray"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFMutableArrayRef"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFArrayRef"), ScriptedSyntheticChildren::Flags());
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("NSDictionary"), ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSMutableDictionary"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFDictionaryRef"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFDictionaryRef"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"), ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSSet synthetic children", ConstString("NSSet"), ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetI synthetic children", ConstString("__NSSetI"), ScriptedSyntheticChildren::Flags());
@@ -930,22 +1113,22 @@ FormatManager::LoadObjCFormatters()
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), ScriptedSyntheticChildren::Flags());
- AddCXXSummary(appkit_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags);
- AddCXXSummary(appkit_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("const struct __CFBag"), appkit_flags);
- AddCXXSummary(appkit_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("const struct __CFBag"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSString"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFStringRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFMutableStringRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFStringRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFMutableStringRef"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSMutableString"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFConstantString"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFString"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFConstantString"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFString"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFConstantString"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFString"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFConstantString"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFString"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSPathStore2"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSAttributedStringSummaryProvider, "NSAttributedString summary provider", ConstString("NSAttributedString"), appkit_flags);
@@ -957,9 +1140,9 @@ 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("__NSCFData"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFDataRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFMutableDataRef"), 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);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSMachPortSummaryProvider, "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags);
@@ -970,10 +1153,11 @@ FormatManager::LoadObjCFormatters()
AddStringSummary(appkit_category_sp,"name:${var.name%S} reason:${var.reason%S}",ConstString("NSException"),appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSNumber"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
+ AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSDecimalNumber summary provider", ConstString("NSDecimalNumber"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSHost summary provider", ConstString("NSHost"), appkit_flags);
@@ -981,7 +1165,7 @@ FormatManager::LoadObjCFormatters()
AddCXXSummary(appkit_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSValue summary provider", ConstString("NSValue"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("NSURL"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("CFURLRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("CFURLRef"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSDate"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSDate"), appkit_flags);
@@ -995,7 +1179,7 @@ FormatManager::LoadObjCFormatters()
// CFAbsoluteTime is actually a double rather than a pointer to an object
// we do not care about the numeric value, since it is probably meaningless to users
appkit_flags.SetDontShowValue(true);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::CFAbsoluteTimeSummaryProvider, "CFAbsoluteTime summary provider", ConstString("CFAbsoluteTime"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFAbsoluteTimeSummaryProvider, "CFAbsoluteTime summary provider", ConstString("CFAbsoluteTime"), appkit_flags);
appkit_flags.SetDontShowValue(false);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags);
@@ -1006,10 +1190,10 @@ FormatManager::LoadObjCFormatters()
ConstString("CFGregorianDate"),
appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFBitVectorRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFMutableBitVectorRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFBitVector"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFMutableBitVector"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFBitVectorRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFMutableBitVectorRef"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFBitVector"), appkit_flags);
+ AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFMutableBitVector"), appkit_flags);
#endif // LLDB_DISABLE_PYTHON
TypeCategoryImpl::SharedPointer vectors_category_sp = GetCategory(m_vectortypes_category_name);
diff --git a/source/DataFormatters/LibCxxUnorderedMap.cpp b/source/DataFormatters/LibCxxUnorderedMap.cpp
new file mode 100644
index 000000000000..b73d3bf852e1
--- /dev/null
+++ b/source/DataFormatters/LibCxxUnorderedMap.cpp
@@ -0,0 +1,135 @@
+//===-- LibCxxUnorderedMap.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#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"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_tree(NULL),
+m_num_elements(0),
+m_next_element(nullptr),
+m_children(),
+m_elements_cache()
+{
+ if (valobj_sp)
+ Update();
+}
+
+size_t
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::CalculateNumChildren ()
+{
+ if (m_num_elements != UINT32_MAX)
+ return m_num_elements;
+ return 0;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (idx >= CalculateNumChildren())
+ return lldb::ValueObjectSP();
+ if (m_tree == NULL)
+ return lldb::ValueObjectSP();
+
+ auto cached = m_children.find(idx);
+ if (cached != m_children.end())
+ return cached->second;
+
+ while (idx >= m_elements_cache.size())
+ {
+ if (m_next_element == nullptr)
+ return lldb::ValueObjectSP();
+
+ Error error;
+ ValueObjectSP node_sp = m_next_element->Dereference(error);
+ if (!node_sp || error.Fail())
+ return lldb::ValueObjectSP();
+
+ ValueObjectSP value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true);
+ ValueObjectSP hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
+ if (!hash_sp || !value_sp)
+ return lldb::ValueObjectSP();
+ m_elements_cache.push_back({value_sp.get(),hash_sp->GetValueAsUnsigned(0)});
+ m_next_element = node_sp->GetChildMemberWithName(ConstString("__next_"),true).get();
+ if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0)
+ m_next_element = nullptr;
+ }
+
+ std::pair<ValueObject*, uint64_t> val_hash = m_elements_cache[idx];
+ if (!val_hash.first)
+ return lldb::ValueObjectSP();
+ StreamString stream;
+ stream.Printf("[%zu]",idx);
+ DataExtractor data;
+ val_hash.first->GetData(data);
+ ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock();
+ return val_hash.first->CreateValueObjectFromData(stream.GetData(),
+ data,
+ exe_ctx,
+ val_hash.first->GetClangType());
+}
+
+bool
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::Update()
+{
+ m_num_elements = UINT32_MAX;
+ m_next_element = nullptr;
+ m_elements_cache.clear();
+ m_children.clear();
+ ValueObjectSP table_sp = m_backend.GetChildMemberWithName(ConstString("__table_"), true);
+ if (!table_sp)
+ return false;
+ ValueObjectSP num_elements_sp = table_sp->GetChildAtNamePath({ConstString("__p2_"),ConstString("__first_")});
+ if (!num_elements_sp)
+ return false;
+ m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
+ m_tree = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get();
+ if (m_num_elements > 0)
+ m_next_element = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get();
+ return false;
+}
+
+bool
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::~LibcxxStdUnorderedMapSyntheticFrontEnd ()
+{}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp));
+}
diff --git a/source/DataFormatters/TypeCategory.cpp b/source/DataFormatters/TypeCategory.cpp
index c887be5da496..636000bb23ea 100644
--- a/source/DataFormatters/TypeCategory.cpp
+++ b/source/DataFormatters/TypeCategory.cpp
@@ -21,6 +21,8 @@ using namespace lldb_private;
TypeCategoryImpl::TypeCategoryImpl(IFormatChangeListener* clist,
ConstString name) :
+m_value_nav(new ValueNavigator("format",clist)),
+m_regex_value_nav(new RegexValueNavigator("regex-format",clist)),
m_summary_nav(new SummaryNavigator("summary",clist)),
m_regex_summary_nav(new RegexSummaryNavigator("regex-summary",clist)),
m_filter_nav(new FilterNavigator("filter",clist)),
@@ -37,6 +39,22 @@ m_name(name)
bool
TypeCategoryImpl::Get (ValueObject& valobj,
+ lldb::TypeFormatImplSP& entry,
+ lldb::DynamicValueType use_dynamic,
+ uint32_t* reason)
+{
+ if (!IsEnabled())
+ return false;
+ if (GetValueNavigator()->Get(valobj, entry, use_dynamic, reason))
+ return true;
+ bool regex = GetRegexValueNavigator()->Get(valobj, entry, use_dynamic, reason);
+ if (regex && reason)
+ *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
+ return regex;
+}
+
+bool
+TypeCategoryImpl::Get (ValueObject& valobj,
lldb::TypeSummaryImplSP& entry,
lldb::DynamicValueType use_dynamic,
uint32_t* reason)
@@ -119,14 +137,21 @@ TypeCategoryImpl::Get(ValueObject& valobj,
void
TypeCategoryImpl::Clear (FormatCategoryItems items)
{
+ if ( (items & eFormatCategoryItemValue) == eFormatCategoryItemValue )
+ m_value_nav->Clear();
+ if ( (items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue )
+ m_regex_value_nav->Clear();
+
if ( (items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary )
m_summary_nav->Clear();
if ( (items & eFormatCategoryItemRegexSummary) == eFormatCategoryItemRegexSummary )
m_regex_summary_nav->Clear();
+
if ( (items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter )
m_filter_nav->Clear();
if ( (items & eFormatCategoryItemRegexFilter) == eFormatCategoryItemRegexFilter )
m_regex_filter_nav->Clear();
+
#ifndef LLDB_DISABLE_PYTHON
if ( (items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth )
m_synth_nav->Clear();
@@ -140,14 +165,22 @@ TypeCategoryImpl::Delete (ConstString name,
FormatCategoryItems items)
{
bool success = false;
+
+ if ( (items & eFormatCategoryItemValue) == eFormatCategoryItemValue )
+ success = m_value_nav->Delete(name) || success;
+ if ( (items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue )
+ success = m_regex_value_nav->Delete(name) || success;
+
if ( (items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary )
success = m_summary_nav->Delete(name) || success;
if ( (items & eFormatCategoryItemRegexSummary) == eFormatCategoryItemRegexSummary )
success = m_regex_summary_nav->Delete(name) || success;
+
if ( (items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter )
success = m_filter_nav->Delete(name) || success;
if ( (items & eFormatCategoryItemRegexFilter) == eFormatCategoryItemRegexFilter )
success = m_regex_filter_nav->Delete(name) || success;
+
#ifndef LLDB_DISABLE_PYTHON
if ( (items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth )
success = m_synth_nav->Delete(name) || success;
@@ -161,14 +194,22 @@ uint32_t
TypeCategoryImpl::GetCount (FormatCategoryItems items)
{
uint32_t count = 0;
+
+ if ( (items & eFormatCategoryItemValue) == eFormatCategoryItemValue )
+ count += m_value_nav->GetCount();
+ if ( (items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue )
+ count += m_regex_value_nav->GetCount();
+
if ( (items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary )
count += m_summary_nav->GetCount();
if ( (items & eFormatCategoryItemRegexSummary) == eFormatCategoryItemRegexSummary )
count += m_regex_summary_nav->GetCount();
+
if ( (items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter )
count += m_filter_nav->GetCount();
if ( (items & eFormatCategoryItemRegexFilter) == eFormatCategoryItemRegexFilter )
count += m_regex_filter_nav->GetCount();
+
#ifndef LLDB_DISABLE_PYTHON
if ( (items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth )
count += m_synth_nav->GetCount();
@@ -188,15 +229,39 @@ TypeCategoryImpl::AnyMatches(ConstString type_name,
if (!IsEnabled() && only_enabled)
return false;
- lldb::TypeSummaryImplSP summary;
- TypeFilterImpl::SharedPointer filter;
+ lldb::TypeFormatImplSP format_sp;
+ lldb::TypeSummaryImplSP summary_sp;
+ TypeFilterImpl::SharedPointer filter_sp;
#ifndef LLDB_DISABLE_PYTHON
- ScriptedSyntheticChildren::SharedPointer synth;
+ ScriptedSyntheticChildren::SharedPointer synth_sp;
#endif
+ if ( (items & eFormatCategoryItemValue) == eFormatCategoryItemValue )
+ {
+ if (m_value_nav->Get(type_name, format_sp))
+ {
+ if (matching_category)
+ *matching_category = m_name.GetCString();
+ if (matching_type)
+ *matching_type = eFormatCategoryItemValue;
+ return true;
+ }
+ }
+ if ( (items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue )
+ {
+ if (m_regex_value_nav->Get(type_name, format_sp))
+ {
+ if (matching_category)
+ *matching_category = m_name.GetCString();
+ if (matching_type)
+ *matching_type = eFormatCategoryItemRegexValue;
+ return true;
+ }
+ }
+
if ( (items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary )
{
- if (m_summary_nav->Get(type_name, summary))
+ if (m_summary_nav->Get(type_name, summary_sp))
{
if (matching_category)
*matching_category = m_name.GetCString();
@@ -207,7 +272,7 @@ TypeCategoryImpl::AnyMatches(ConstString type_name,
}
if ( (items & eFormatCategoryItemRegexSummary) == eFormatCategoryItemRegexSummary )
{
- if (m_regex_summary_nav->Get(type_name, summary))
+ if (m_regex_summary_nav->Get(type_name, summary_sp))
{
if (matching_category)
*matching_category = m_name.GetCString();
@@ -216,9 +281,10 @@ TypeCategoryImpl::AnyMatches(ConstString type_name,
return true;
}
}
+
if ( (items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter )
{
- if (m_filter_nav->Get(type_name, filter))
+ if (m_filter_nav->Get(type_name, filter_sp))
{
if (matching_category)
*matching_category = m_name.GetCString();
@@ -229,7 +295,7 @@ TypeCategoryImpl::AnyMatches(ConstString type_name,
}
if ( (items & eFormatCategoryItemRegexFilter) == eFormatCategoryItemRegexFilter )
{
- if (m_regex_filter_nav->Get(type_name, filter))
+ if (m_regex_filter_nav->Get(type_name, filter_sp))
{
if (matching_category)
*matching_category = m_name.GetCString();
@@ -238,10 +304,11 @@ TypeCategoryImpl::AnyMatches(ConstString type_name,
return true;
}
}
+
#ifndef LLDB_DISABLE_PYTHON
if ( (items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth )
{
- if (m_synth_nav->Get(type_name, synth))
+ if (m_synth_nav->Get(type_name, synth_sp))
{
if (matching_category)
*matching_category = m_name.GetCString();
@@ -252,7 +319,7 @@ TypeCategoryImpl::AnyMatches(ConstString type_name,
}
if ( (items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth )
{
- if (m_regex_synth_nav->Get(type_name, synth))
+ if (m_regex_synth_nav->Get(type_name, synth_sp))
{
if (matching_category)
*matching_category = m_name.GetCString();
@@ -265,6 +332,22 @@ TypeCategoryImpl::AnyMatches(ConstString type_name,
return false;
}
+TypeCategoryImpl::ValueNavigator::MapValueType
+TypeCategoryImpl::GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp)
+{
+ ValueNavigator::MapValueType retval;
+
+ if (type_sp)
+ {
+ if (type_sp->IsRegex())
+ m_regex_value_nav->GetExact(ConstString(type_sp->GetName()),retval);
+ else
+ m_value_nav->GetExact(ConstString(type_sp->GetName()),retval);
+ }
+
+ return retval;
+}
+
TypeCategoryImpl::SummaryNavigator::MapValueType
TypeCategoryImpl::GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp)
{
@@ -324,6 +407,15 @@ TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex (size_t index)
return m_regex_summary_nav->GetTypeNameSpecifierAtIndex(index-m_summary_nav->GetCount());
}
+TypeCategoryImpl::ValueNavigator::MapValueType
+TypeCategoryImpl::GetFormatAtIndex (size_t index)
+{
+ if (index < m_value_nav->GetCount())
+ return m_value_nav->GetAtIndex(index);
+ else
+ return m_regex_value_nav->GetAtIndex(index-m_value_nav->GetCount());
+}
+
TypeCategoryImpl::SummaryNavigator::MapValueType
TypeCategoryImpl::GetSummaryAtIndex (size_t index)
{
@@ -343,6 +435,15 @@ TypeCategoryImpl::GetFilterAtIndex (size_t index)
}
lldb::TypeNameSpecifierImplSP
+TypeCategoryImpl::GetTypeNameSpecifierForFormatAtIndex (size_t index)
+{
+ if (index < m_value_nav->GetCount())
+ return m_value_nav->GetTypeNameSpecifierAtIndex(index);
+ else
+ return m_regex_value_nav->GetTypeNameSpecifierAtIndex(index-m_value_nav->GetCount());
+}
+
+lldb::TypeNameSpecifierImplSP
TypeCategoryImpl::GetTypeNameSpecifierForFilterAtIndex (size_t index)
{
if (index < m_filter_nav->GetCount())
diff --git a/source/DataFormatters/TypeCategoryMap.cpp b/source/DataFormatters/TypeCategoryMap.cpp
index 4b7222adbec7..621258806def 100644
--- a/source/DataFormatters/TypeCategoryMap.cpp
+++ b/source/DataFormatters/TypeCategoryMap.cpp
@@ -176,6 +176,32 @@ TypeCategoryMap::AnyMatches (ConstString type_name,
return false;
}
+lldb::TypeFormatImplSP
+TypeCategoryMap::GetFormat (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
+{
+ Mutex::Locker locker(m_map_mutex);
+
+ uint32_t reason_why;
+ ActiveCategoriesIterator begin, end = m_active_categories.end();
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+
+ for (begin = m_active_categories.begin(); begin != end; begin++)
+ {
+ lldb::TypeCategoryImplSP category_sp = *begin;
+ lldb::TypeFormatImplSP current_format;
+ if (log)
+ log->Printf("\n[TypeCategoryMap::GetFormat] Trying to use category %s", category_sp->GetName());
+ if (!category_sp->Get(valobj, current_format, use_dynamic, &reason_why))
+ continue;
+ return current_format;
+ }
+ if (log)
+ log->Printf("[TypeCategoryMap::GetFormat] nothing found - returning empty SP");
+ return lldb::TypeFormatImplSP();
+}
+
lldb::TypeSummaryImplSP
TypeCategoryMap::GetSummaryFormat (ValueObject& valobj,
lldb::DynamicValueType use_dynamic)
diff --git a/source/DataFormatters/TypeFormat.cpp b/source/DataFormatters/TypeFormat.cpp
index 279704f2af12..7f18ddef7264 100644
--- a/source/DataFormatters/TypeFormat.cpp
+++ b/source/DataFormatters/TypeFormat.cpp
@@ -42,7 +42,7 @@ std::string
TypeFormatImpl::GetDescription()
{
StreamString sstr;
- sstr.Printf ("%s%s%s%s\n",
+ sstr.Printf ("%s%s%s%s",
FormatManager::GetFormatAsCString (GetFormat()),
Cascades() ? "" : " (not cascading)",
SkipsPointers() ? " (skip pointers)" : "",
diff --git a/source/DataFormatters/TypeSummary.cpp b/source/DataFormatters/TypeSummary.cpp
index 8c4d3f71c050..4c75b4b87d03 100644
--- a/source/DataFormatters/TypeSummary.cpp
+++ b/source/DataFormatters/TypeSummary.cpp
@@ -23,6 +23,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Target/StackFrame.h"
@@ -65,51 +66,12 @@ StringSummaryFormat::FormatObject (ValueObject *valobj,
if (frame)
sc = frame->GetSymbolContext(lldb::eSymbolContextEverything);
- if (IsOneliner())
+ if (IsOneLiner())
{
- ValueObject* object;
-
- ValueObjectSP synth_valobj = valobj->GetSyntheticValue();
- if (synth_valobj)
- object = synth_valobj.get();
- else
- object = valobj;
-
- const uint32_t num_children = object->GetNumChildren();
- if (num_children)
- {
- s.PutChar('(');
-
- for (uint32_t idx=0; idx<num_children; ++idx)
- {
- lldb::ValueObjectSP child_sp(object->GetChildAtIndex(idx, true));
- if (child_sp.get())
- {
- if (idx)
- s.PutCString(", ");
- if (!HideNames())
- {
- s.PutCString(child_sp.get()->GetName().AsCString());
- s.PutCString(" = ");
- }
- child_sp.get()->DumpPrintableRepresentation(s,
- ValueObject::eValueObjectRepresentationStyleSummary,
- lldb::eFormatInvalid,
- ValueObject::ePrintableRepresentationSpecialCasesDisable);
- }
- }
-
- s.PutChar(')');
-
- retval.assign(s.GetString());
- return true;
- }
- else
- {
- retval.assign("error: oneliner for no children");
- return false;
- }
-
+ ValueObjectPrinter printer(valobj,&s,DumpValueObjectOptions());
+ printer.PrintChildrenOneLiner(HideNames());
+ retval.assign(s.GetData());
+ return true;
}
else
{
@@ -135,7 +97,7 @@ StringSummaryFormat::GetDescription ()
Cascades() ? "" : " (not cascading)",
!DoesPrintChildren() ? "" : " (show children)",
!DoesPrintValue() ? " (hide value)" : "",
- IsOneliner() ? " (one-line printout)" : "",
+ IsOneLiner() ? " (one-line printout)" : "",
SkipsPointers() ? " (skip pointers)" : "",
SkipsReferences() ? " (skip references)" : "",
HideNames() ? " (hide member names)" : "");
@@ -171,7 +133,7 @@ CXXFunctionSummaryFormat::GetDescription ()
Cascades() ? "" : " (not cascading)",
!DoesPrintChildren() ? "" : " (show children)",
!DoesPrintValue() ? " (hide value)" : "",
- IsOneliner() ? " (one-line printout)" : "",
+ IsOneLiner() ? " (one-line printout)" : "",
SkipsPointers() ? " (skip pointers)" : "",
SkipsReferences() ? " (skip references)" : "",
HideNames() ? " (hide member names)" : "");
@@ -238,7 +200,7 @@ ScriptSummaryFormat::GetDescription ()
sstr.Printf ("%s%s%s%s%s%s%s\n%s", Cascades() ? "" : " (not cascading)",
!DoesPrintChildren() ? "" : " (show children)",
!DoesPrintValue() ? " (hide value)" : "",
- IsOneliner() ? " (one-line printout)" : "",
+ IsOneLiner() ? " (one-line printout)" : "",
SkipsPointers() ? " (skip pointers)" : "",
SkipsReferences() ? " (skip references)" : "",
HideNames() ? " (hide member names)" : "",
diff --git a/source/DataFormatters/ValueObjectPrinter.cpp b/source/DataFormatters/ValueObjectPrinter.cpp
new file mode 100644
index 000000000000..5c7f48b600bf
--- /dev/null
+++ b/source/DataFormatters/ValueObjectPrinter.cpp
@@ -0,0 +1,623 @@
+//===-- ValueObjectPrinter.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/DataFormatters/ValueObjectPrinter.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Debugger.h"
+#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
+ Stream* s,
+ const DumpValueObjectOptions& options)
+{
+ Init(valobj,s,options,options.m_max_ptr_depth,0);
+}
+
+ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
+ Stream* s,
+ const DumpValueObjectOptions& options,
+ uint32_t ptr_depth,
+ uint32_t curr_depth)
+{
+ Init(valobj,s,options,ptr_depth,curr_depth);
+}
+
+void
+ValueObjectPrinter::Init (ValueObject* valobj,
+ Stream* s,
+ const DumpValueObjectOptions& options,
+ uint32_t ptr_depth,
+ uint32_t curr_depth)
+{
+ m_orig_valobj = valobj;
+ m_valobj = nullptr;
+ m_stream = s;
+ this->options = options;
+ m_ptr_depth = ptr_depth;
+ m_curr_depth = curr_depth;
+ assert (m_orig_valobj && "cannot print a NULL ValueObject");
+ assert (m_stream && "cannot print to a NULL Stream");
+ m_should_print = eLazyBoolCalculate;
+ m_is_nil = eLazyBoolCalculate;
+ m_is_ptr = eLazyBoolCalculate;
+ m_is_ref = eLazyBoolCalculate;
+ m_is_aggregate = eLazyBoolCalculate;
+ m_summary_formatter = {nullptr,false};
+ m_value.assign("");
+ m_summary.assign("");
+ m_error.assign("");
+}
+
+bool
+ValueObjectPrinter::PrintValueObject ()
+{
+ if (!GetDynamicValueIfNeeded () || m_valobj == nullptr)
+ return false;
+
+ if (ShouldPrintValueObject())
+ {
+ PrintLocationIfNeeded();
+ m_stream->Indent();
+
+ bool show_type = PrintTypeIfNeeded();
+
+ PrintNameIfNeeded(show_type);
+ }
+
+ bool value_printed = false;
+ bool summary_printed = false;
+
+ bool val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed);
+
+ if (val_summary_ok)
+ PrintChildrenIfNeeded (value_printed, summary_printed);
+ else
+ m_stream->EOL();
+
+ return true;
+}
+
+bool
+ValueObjectPrinter::GetDynamicValueIfNeeded ()
+{
+ if (m_valobj)
+ return true;
+ bool update_success = m_orig_valobj->UpdateValueIfNeeded (true);
+ if (!update_success)
+ {
+ m_valobj = m_orig_valobj;
+ }
+ else
+ {
+ if (m_orig_valobj->IsDynamic())
+ {
+ if (options.m_use_dynamic == eNoDynamicValues)
+ {
+ ValueObject *static_value = m_orig_valobj->GetStaticValue().get();
+ if (static_value)
+ m_valobj = static_value;
+ else
+ m_valobj = m_orig_valobj;
+ }
+ else
+ m_valobj = m_orig_valobj;
+ }
+ else
+ {
+ if (options.m_use_dynamic != eNoDynamicValues)
+ {
+ ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(options.m_use_dynamic).get();
+ if (dynamic_value)
+ m_valobj = dynamic_value;
+ else
+ m_valobj = m_orig_valobj;
+ }
+ else
+ m_valobj = m_orig_valobj;
+ }
+ }
+ m_clang_type = m_valobj->GetClangType();
+ m_type_flags = m_clang_type.GetTypeInfo ();
+ return true;
+}
+
+const char*
+ValueObjectPrinter::GetDescriptionForDisplay ()
+{
+ const char* str = m_valobj->GetObjectDescription();
+ if (!str)
+ str = m_valobj->GetSummaryAsCString();
+ if (!str)
+ str = m_valobj->GetValueAsCString();
+ return str;
+}
+
+const char*
+ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail)
+{
+ const char *root_valobj_name = options.m_root_valobj_name.empty() ?
+ m_valobj->GetName().AsCString() :
+ options.m_root_valobj_name.c_str();
+ return root_valobj_name ? root_valobj_name : if_fail;
+}
+
+bool
+ValueObjectPrinter::ShouldPrintValueObject ()
+{
+ if (m_should_print == eLazyBoolCalculate)
+ m_should_print = (options.m_flat_output == false || m_type_flags.Test (ClangASTType::eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo;
+ return m_should_print == eLazyBoolYes;
+}
+
+bool
+ValueObjectPrinter::IsNil ()
+{
+ if (m_is_nil == eLazyBoolCalculate)
+ m_is_nil = m_valobj->IsObjCNil() ? eLazyBoolYes : eLazyBoolNo;
+ return m_is_nil == eLazyBoolYes;
+}
+
+bool
+ValueObjectPrinter::IsPtr ()
+{
+ if (m_is_ptr == eLazyBoolCalculate)
+ m_is_ptr = m_type_flags.Test (ClangASTType::eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo;
+ return m_is_ptr == eLazyBoolYes;
+}
+
+bool
+ValueObjectPrinter::IsRef ()
+{
+ if (m_is_ref == eLazyBoolCalculate)
+ m_is_ref = m_type_flags.Test (ClangASTType::eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo;
+ return m_is_ref == eLazyBoolYes;
+}
+
+bool
+ValueObjectPrinter::IsAggregate ()
+{
+ if (m_is_aggregate == eLazyBoolCalculate)
+ m_is_aggregate = m_type_flags.Test (ClangASTType::eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo;
+ return m_is_aggregate == eLazyBoolYes;
+}
+
+bool
+ValueObjectPrinter::PrintLocationIfNeeded ()
+{
+ if (options.m_show_location)
+ {
+ m_stream->Printf("%s: ", m_valobj->GetLocationAsCString());
+ return true;
+ }
+ return false;
+}
+
+bool
+ValueObjectPrinter::PrintTypeIfNeeded ()
+{
+ bool show_type = true;
+ // if we are at the root-level and been asked to hide the root's type, then hide it
+ if (m_curr_depth == 0 && options.m_hide_root_type)
+ show_type = false;
+ else
+ // otherwise decide according to the usual rules (asked to show types - always at the root level)
+ show_type = options.m_show_types || (m_curr_depth == 0 && !options.m_flat_output);
+
+ if (show_type)
+ {
+ // 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());
+ if (qualified_type_name)
+ m_stream->Printf("(%s) ", qualified_type_name.GetCString());
+ else
+ show_type = false;
+ }
+ return show_type;
+}
+
+bool
+ValueObjectPrinter::PrintNameIfNeeded (bool show_type)
+{
+ if (options.m_flat_output)
+ {
+ // If we are showing types, also qualify the C++ base classes
+ const bool qualify_cxx_base_classes = show_type;
+ if (!options.m_hide_name)
+ {
+ m_valobj->GetExpressionPath(*m_stream, qualify_cxx_base_classes);
+ m_stream->PutCString(" =");
+ return true;
+ }
+ }
+ else if (!options.m_hide_name)
+ {
+ const char *name_cstr = GetRootNameForDisplay("");
+ m_stream->Printf ("%s =", name_cstr);
+ return true;
+ }
+ return false;
+}
+
+bool
+ValueObjectPrinter::CheckScopeIfNeeded ()
+{
+ if (options.m_scope_already_checked)
+ return true;
+ return m_valobj->IsInScope();
+}
+
+TypeSummaryImpl*
+ValueObjectPrinter::GetSummaryFormatter ()
+{
+ if (m_summary_formatter.second == false)
+ {
+ TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get();
+
+ if (options.m_omit_summary_depth > 0)
+ entry = NULL;
+ m_summary_formatter.first = entry;
+ m_summary_formatter.second = true;
+ }
+ return m_summary_formatter.first;
+}
+
+void
+ValueObjectPrinter::GetValueSummaryError (std::string& value,
+ std::string& summary,
+ std::string& error)
+{
+ if (options.m_format != eFormatDefault && options.m_format != m_valobj->GetFormat())
+ {
+ m_valobj->GetValueAsCString(options.m_format,
+ value);
+ }
+ else
+ {
+ const char* val_cstr = m_valobj->GetValueAsCString();
+ if (val_cstr)
+ value.assign(val_cstr);
+ }
+ const char* err_cstr = m_valobj->GetError().AsCString();
+ if (err_cstr)
+ error.assign(err_cstr);
+
+ if (ShouldPrintValueObject())
+ {
+ if (IsNil())
+ summary.assign("nil");
+ else if (options.m_omit_summary_depth == 0)
+ {
+ TypeSummaryImpl* entry = GetSummaryFormatter();
+ if (entry)
+ m_valobj->GetSummaryAsCString(entry, summary);
+ else
+ {
+ const char* sum_cstr = m_valobj->GetSummaryAsCString();
+ if (sum_cstr)
+ summary.assign(sum_cstr);
+ }
+ }
+ }
+}
+
+bool
+ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed,
+ bool& summary_printed)
+{
+ bool error_printed = false;
+ if (ShouldPrintValueObject())
+ {
+ if (!CheckScopeIfNeeded())
+ m_error.assign("out of scope");
+ if (m_error.empty())
+ {
+ GetValueSummaryError(m_value, m_summary, m_error);
+ }
+ if (m_error.size())
+ {
+ error_printed = true;
+ m_stream->Printf (" <%s>\n", m_error.c_str());
+ }
+ else
+ {
+ // Make sure we have a value and make sure the summary didn't
+ // specify that the value should not be printed - and do not print
+ // 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)
+ {
+ m_stream->Printf(" %s", m_value.c_str());
+ value_printed = true;
+ }
+
+ if (m_summary.size())
+ {
+ m_stream->Printf(" %s", m_summary.c_str());
+ summary_printed = true;
+ }
+ }
+ }
+ return !error_printed;
+}
+
+bool
+ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed,
+ bool summary_printed)
+{
+ if (ShouldPrintValueObject())
+ {
+ // let's avoid the overly verbose no description error for a nil thing
+ if (options.m_use_objc && !IsNil())
+ {
+ if (!options.m_hide_value || !options.m_hide_name)
+ m_stream->Printf(" ");
+ const char *object_desc = nullptr;
+ if (value_printed || summary_printed)
+ object_desc = m_valobj->GetObjectDescription();
+ else
+ object_desc = GetDescriptionForDisplay();
+ if (object_desc && *object_desc)
+ {
+ m_stream->Printf("%s\n", object_desc);
+ return true;
+ }
+ else if (value_printed == false && summary_printed == false)
+ return true;
+ else
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
+ uint32_t& curr_ptr_depth)
+{
+ const bool is_ref = IsRef ();
+ const bool is_ptr = IsPtr ();
+
+ if (is_failed_description || m_curr_depth < options.m_max_depth)
+ {
+ // We will show children for all concrete types. We won't show
+ // pointer contents unless a pointer depth has been specified.
+ // We won't reference contents unless the reference is the
+ // root object (depth of zero).
+
+ // Use a new temporary pointer depth in case we override the
+ // current pointer depth below...
+ uint32_t curr_ptr_depth = m_ptr_depth;
+
+ if (is_ptr || is_ref)
+ {
+ // We have a pointer or reference whose value is an address.
+ // Make sure that address is not NULL
+ AddressType ptr_address_type;
+ if (m_valobj->GetPointerValue (&ptr_address_type) == 0)
+ return false;
+
+ else if (is_ref && m_curr_depth == 0)
+ {
+ // If this is the root object (depth is zero) that we are showing
+ // and it is a reference, and no pointer depth has been supplied
+ // print out what it references. Don't do this at deeper depths
+ // otherwise we can end up with infinite recursion...
+ curr_ptr_depth = 1;
+ }
+
+ return (curr_ptr_depth > 0);
+ }
+
+ TypeSummaryImpl* entry = GetSummaryFormatter();
+
+ return (!entry || entry->DoesPrintChildren() || m_summary.empty());
+ }
+ return false;
+}
+
+ValueObject*
+ValueObjectPrinter::GetValueObjectForChildrenGeneration ()
+{
+ ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic);
+ return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj);
+}
+
+void
+ValueObjectPrinter::PrintChildrenPreamble ()
+{
+ if (options.m_flat_output)
+ {
+ if (ShouldPrintValueObject())
+ m_stream->EOL();
+ }
+ else
+ {
+ if (ShouldPrintValueObject())
+ m_stream->PutCString(IsRef () ? ": {\n" : " {\n");
+ m_stream->IndentMore();
+ }
+}
+
+void
+ValueObjectPrinter::PrintChild (ValueObjectSP child_sp,
+ uint32_t curr_ptr_depth)
+{
+ DumpValueObjectOptions child_options(options);
+ child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName();
+ child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value)
+ .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0);
+ if (child_sp.get())
+ {
+ ValueObjectPrinter child_printer(child_sp.get(),
+ m_stream,
+ child_options,
+ (IsPtr() || IsRef()) ? curr_ptr_depth - 1 : curr_ptr_depth,
+ m_curr_depth + 1);
+ child_printer.PrintValueObject();
+ }
+
+}
+
+uint32_t
+ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot)
+{
+ ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
+
+ size_t num_children = synth_m_valobj->GetNumChildren();
+ print_dotdotdot = false;
+ if (num_children)
+ {
+ const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
+
+ if (num_children > max_num_children && !options.m_ignore_cap)
+ {
+ print_dotdotdot = true;
+ return max_num_children;
+ }
+ }
+ return num_children;
+}
+
+void
+ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot)
+{
+ if (!options.m_flat_output)
+ {
+ if (print_dotdotdot)
+ {
+ m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated();
+ m_stream->Indent("...\n");
+ }
+ m_stream->IndentLess();
+ m_stream->Indent("}\n");
+ }
+}
+
+void
+ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth)
+{
+ ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
+
+ bool print_dotdotdot = false;
+ size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
+ if (num_children)
+ {
+ PrintChildrenPreamble ();
+
+ for (size_t idx=0; idx<num_children; ++idx)
+ {
+ ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
+ PrintChild (child_sp, curr_ptr_depth);
+ }
+
+ PrintChildrenPostamble (print_dotdotdot);
+ }
+ else if (IsAggregate())
+ {
+ // Aggregate, no children...
+ if (ShouldPrintValueObject())
+ m_stream->PutCString(" {}\n");
+ }
+ else
+ {
+ if (ShouldPrintValueObject())
+ m_stream->EOL();
+ }
+}
+
+bool
+ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names)
+{
+ if (!GetDynamicValueIfNeeded () || m_valobj == nullptr)
+ return false;
+
+ ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
+
+ bool print_dotdotdot = false;
+ size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
+
+ if (num_children)
+ {
+ m_stream->PutChar('(');
+
+ for (uint32_t idx=0; idx<num_children; ++idx)
+ {
+ lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
+ lldb::ValueObjectSP child_dyn_sp = child_sp.get() ? child_sp->GetDynamicValue(options.m_use_dynamic) : child_sp;
+ if (child_dyn_sp)
+ child_sp = child_dyn_sp;
+ if (child_sp)
+ {
+ if (idx)
+ m_stream->PutCString(", ");
+ if (!hide_names)
+ {
+ const char* name = child_sp.get()->GetName().AsCString();
+ if (name && *name)
+ {
+ m_stream->PutCString(name);
+ m_stream->PutCString(" = ");
+ }
+ }
+ child_sp->DumpPrintableRepresentation(*m_stream,
+ ValueObject::eValueObjectRepresentationStyleSummary,
+ lldb::eFormatInvalid,
+ ValueObject::ePrintableRepresentationSpecialCasesDisable);
+ }
+ }
+
+ if (print_dotdotdot)
+ m_stream->PutCString(", ...)");
+ else
+ m_stream->PutChar(')');
+ }
+ return true;
+}
+
+void
+ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
+ bool summary_printed)
+{
+ // this flag controls whether we tried to display a description for this object and failed
+ // if that happens, we want to display the children, if any
+ bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
+
+ uint32_t curr_ptr_depth = m_ptr_depth;
+ bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth);
+ bool print_oneline = (curr_ptr_depth > 0 || options.m_show_types || options.m_be_raw) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
+
+ if (print_children)
+ {
+ if (print_oneline)
+ {
+ m_stream->PutChar(' ');
+ PrintChildrenOneLiner (false);
+ m_stream->EOL();
+ }
+ else
+ PrintChildren (curr_ptr_depth);
+ }
+ else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject())
+ {
+ m_stream->PutCString("{...}\n");
+ }
+ else
+ m_stream->EOL();
+}
diff --git a/source/Expression/ClangASTSource.cpp b/source/Expression/ClangASTSource.cpp
index 49513d740f30..316efdf9c149 100644
--- a/source/Expression/ClangASTSource.cpp
+++ b/source/Expression/ClangASTSource.cpp
@@ -878,31 +878,34 @@ FindObjCMethodDeclsWithOrigin (unsigned int current_id,
if (!result[0])
return false;
- ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(result[0]);
-
- 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)
+ for (NamedDecl *named_decl : result)
{
- ASTDumper dumper((Decl*)copied_method_decl);
- log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, dumper.GetCString());
+ 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);
}
- context.AddNamedDecl(copied_method_decl);
-
return true;
}
diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp
index 072e7819cd02..87c984ddcfb9 100644
--- a/source/Expression/ClangExpressionDeclMap.cpp
+++ b/source/Expression/ClangExpressionDeclMap.cpp
@@ -21,6 +21,7 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectVariable.h"
@@ -514,6 +515,7 @@ FindCodeSymbolInContext
{
case eSymbolTypeCode:
case eSymbolTypeResolver:
+ case eSymbolTypeReExported:
sc_list.Append(sym_ctx);
break;
@@ -546,7 +548,8 @@ ClangExpressionDeclMap::GetFunctionAddress
FindCodeSymbolInContext(name, m_parser_vars->m_sym_ctx, sc_list);
- if (!sc_list.GetSize())
+ 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
// as non-const, so the mangled name is wrong. This is a hack to compensate.
@@ -562,40 +565,64 @@ ClangExpressionDeclMap::GetFunctionAddress
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();
}
}
-
- if (!sc_list.GetSize())
- return false;
-
- SymbolContext sym_ctx;
- sc_list.GetContextAtIndex(0, sym_ctx);
- const Address *func_so_addr = NULL;
- bool is_indirect_function = false;
-
- if (sym_ctx.function)
- func_so_addr = &sym_ctx.function->GetAddressRange().GetBaseAddress();
- else if (sym_ctx.symbol) {
- func_so_addr = &sym_ctx.symbol->GetAddress();
- is_indirect_function = sym_ctx.symbol->IsIndirect();
- } else
- return false;
-
- if (!func_so_addr || !func_so_addr->IsValid())
- return false;
+ for (uint32_t i=0; i<sc_list_size; ++i)
+ {
+ SymbolContext sym_ctx;
+ sc_list.GetContextAtIndex(i, sym_ctx);
- func_addr = func_so_addr->GetCallableLoadAddress (target, is_indirect_function);
+ const Address *func_so_addr = NULL;
+ bool is_indirect_function = false;
+ 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
+ {
+ func_so_addr = &sym_ctx.symbol->GetAddress();
+ is_indirect_function = sym_ctx.symbol->IsIndirect();
+ }
+ }
- return true;
+ if (func_so_addr && func_so_addr->IsValid())
+ {
+ 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;
+ }
+ }
+ }
+ return false;
}
addr_t
-ClangExpressionDeclMap::GetSymbolAddress (Target &target, Process *process, const ConstString &name, lldb::SymbolType symbol_type)
+ClangExpressionDeclMap::GetSymbolAddress (Target &target,
+ Process *process,
+ const ConstString &name,
+ lldb::SymbolType symbol_type,
+ lldb_private::Module *module)
{
SymbolContextList sc_list;
- target.GetImages().FindSymbolsWithNameAndType(name, symbol_type, 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;
@@ -623,6 +650,28 @@ ClangExpressionDeclMap::GetSymbolAddress (Target &target, Process *process, cons
symbol_load_addr = sym_address->GetCallableLoadAddress (&target, true);
break;
+ case eSymbolTypeReExported:
+ {
+ ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName();
+ if (reexport_name)
+ {
+ ModuleSP reexport_module_sp;
+ ModuleSpec reexport_module_spec;
+ reexport_module_spec.GetPlatformFileSpec() = sym_ctx.symbol->GetReExportedSymbolSharedLibrary();
+ if (reexport_module_spec.GetPlatformFileSpec())
+ {
+ reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec);
+ if (!reexport_module_sp)
+ {
+ reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear();
+ reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec);
+ }
+ }
+ symbol_load_addr = GetSymbolAddress(target, process, sym_ctx.symbol->GetReExportedSymbolName(), symbol_type, reexport_module_sp.get());
+ }
+ }
+ break;
+
case eSymbolTypeData:
case eSymbolTypeRuntime:
case eSymbolTypeVariable:
@@ -680,11 +729,15 @@ ClangExpressionDeclMap::GetSymbolAddress (const ConstString &name, lldb::SymbolT
const Symbol *
ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target,
- const ConstString &name)
+ const ConstString &name,
+ lldb_private::Module *module)
{
SymbolContextList sc_list;
- target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, 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)
@@ -716,6 +769,28 @@ ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target,
}
return symbol;
+ case eSymbolTypeReExported:
+ {
+ ConstString reexport_name = symbol->GetReExportedSymbolName();
+ if (reexport_name)
+ {
+ ModuleSP reexport_module_sp;
+ ModuleSpec reexport_module_spec;
+ reexport_module_spec.GetPlatformFileSpec() = symbol->GetReExportedSymbolSharedLibrary();
+ if (reexport_module_spec.GetPlatformFileSpec())
+ {
+ reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec);
+ if (!reexport_module_sp)
+ {
+ reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear();
+ reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec);
+ }
+ }
+ return FindGlobalDataSymbol(target, symbol->GetReExportedSymbolName(), reexport_module_sp.get());
+ }
+ }
+ break;
+
case eSymbolTypeCode: // We already lookup functions elsewhere
case eSymbolTypeVariable:
case eSymbolTypeLocal:
@@ -1286,7 +1361,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
if (sc_list.GetSize())
{
- Symbol *generic_symbol = NULL;
+ Symbol *extern_symbol = NULL;
Symbol *non_extern_symbol = NULL;
for (uint32_t index = 0, num_indices = sc_list.GetSize();
@@ -1315,8 +1390,15 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
}
else if (sym_ctx.symbol)
{
+ if (sym_ctx.symbol->GetType() == eSymbolTypeReExported)
+ {
+ sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target);
+ if (sym_ctx.symbol == NULL)
+ continue;
+ }
+
if (sym_ctx.symbol->IsExternal())
- generic_symbol = sym_ctx.symbol;
+ extern_symbol = sym_ctx.symbol;
else
non_extern_symbol = sym_ctx.symbol;
}
@@ -1324,9 +1406,9 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
if (!context.m_found.function_with_type_info)
{
- if (generic_symbol)
+ if (extern_symbol)
{
- AddOneFunction (context, NULL, generic_symbol, current_id);
+ AddOneFunction (context, NULL, extern_symbol, current_id);
context.m_found.function = true;
}
else if (non_extern_symbol)
@@ -1418,7 +1500,6 @@ ClangExpressionDeclMap::GetVariableValue (VariableSP &var,
return false;
}
- // commented out because of <rdar://problem/11024417>
ASTContext *ast = var_type->GetClangASTContext().getASTContext();
if (!ast)
diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp
index 98c0bfdca874..f0de1edc90d3 100644
--- a/source/Expression/ClangExpressionParser.cpp
+++ b/source/Expression/ClangExpressionParser.cpp
@@ -55,10 +55,6 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/TargetSelect.h"
-#if defined(__FreeBSD__)
-#define USE_STANDARD_JIT
-#endif
-
#if defined (USE_STANDARD_JIT)
#include "llvm/ExecutionEngine/JIT.h"
#else
@@ -119,7 +115,6 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
case ASTDump: return new ASTDumpAction();
case ASTPrint: return new ASTPrintAction();
- case ASTDumpXML: return new ASTDumpXMLAction();
case ASTView: return new ASTViewAction();
case DumpRawTokens: return new DumpRawTokensAction();
case DumpTokens: return new DumpTokensAction();
@@ -195,8 +190,6 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
llvm::InitializeAllAsmPrinters();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllDisassemblers();
-
- llvm::DisablePrettyStackTrace = true;
}
} InitializeLLVM;
@@ -318,6 +311,8 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
// Set CodeGen options
m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
m_compiler->getCodeGenOpts().InstrumentFunctions = false;
+ m_compiler->getCodeGenOpts().DisableFPElim = true;
+ m_compiler->getCodeGenOpts().OmitLeafFramePointer = false;
// Disable some warnings.
m_compiler->getDiagnostics().setDiagnosticGroupMapping("unused-value", clang::diag::MAP_IGNORE, SourceLocation());
diff --git a/source/Expression/ClangFunction.cpp b/source/Expression/ClangFunction.cpp
index 177138df801b..b37044df9ecc 100644
--- a/source/Expression/ClangFunction.cpp
+++ b/source/Expression/ClangFunction.cpp
@@ -80,7 +80,6 @@ ClangFunction::ClangFunction
m_function_ptr (&function),
m_function_addr (),
m_function_return_type (),
- m_clang_ast_context (ast_context),
m_wrapper_function_name ("__lldb_function_caller"),
m_wrapper_struct_name ("__lldb_caller_struct"),
m_wrapper_args_addrs (),
@@ -112,7 +111,7 @@ ClangFunction::CompileFunction (Stream &errors)
// FIXME: How does clang tell us there's no return value? We need to handle that case.
unsigned num_errors = 0;
- std::string return_type_str (m_function_return_type.GetTypeName());
+ std::string return_type_str (m_function_return_type.GetTypeName().AsCString(""));
// Cons up the function we're going to wrap our call in, then compile it...
// We declare the function "extern "C"" because the compiler might be in C++
@@ -163,18 +162,18 @@ ClangFunction::CompileFunction (Stream &errors)
if (trust_function)
{
- type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName();
+ type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString("");
}
else
{
ClangASTType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetClangType ();
if (clang_qual_type)
{
- type_name = clang_qual_type.GetTypeName();
+ type_name = clang_qual_type.GetTypeName().AsCString("");
}
else
{
- errors.Printf("Could not determine type of input value %lu.", i);
+ errors.Printf("Could not determine type of input value %zu.", i);
return 1;
}
}
@@ -345,7 +344,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: %lu should be: %lu", num_args, m_arg_values.GetSize());
+ errors.Printf ("Wrong number of arguments - was: %zu should be: %zu", num_args, m_arg_values.GetSize());
return false;
}
@@ -629,5 +628,7 @@ ClangFunction::ExecuteFunction(
clang::ASTConsumer *
ClangFunction::ASTTransformer (clang::ASTConsumer *passthrough)
{
- return new ASTStructExtractor(passthrough, m_wrapper_struct_name.c_str(), *this);
+ m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_wrapper_struct_name.c_str(), *this));
+
+ return m_struct_extractor.get();
}
diff --git a/source/Expression/ClangUserExpression.cpp b/source/Expression/ClangUserExpression.cpp
index 7f09f6fa0942..e4f2830ba259 100644
--- a/source/Expression/ClangUserExpression.cpp
+++ b/source/Expression/ClangUserExpression.cpp
@@ -95,15 +95,9 @@ ClangUserExpression::~ClangUserExpression ()
clang::ASTConsumer *
ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
-{
- ClangASTContext *clang_ast_context = m_target->GetScratchClangASTContext();
-
- if (!clang_ast_context)
- return NULL;
-
- if (!m_result_synthesizer.get())
- m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough,
- *m_target));
+{
+ m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough,
+ *m_target));
return m_result_synthesizer.get();
}
@@ -508,6 +502,9 @@ ClangUserExpression::Parse (Stream &error_stream,
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;
}
@@ -525,7 +522,7 @@ ClangUserExpression::Parse (Stream &error_stream,
{
error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
- m_expr_decl_map->DidParse();
+ m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.
return false;
}
@@ -540,6 +537,8 @@ ClangUserExpression::Parse (Stream &error_stream,
exe_ctx,
m_can_interpret,
execution_policy);
+
+ 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())
{
@@ -785,12 +784,9 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
ExecutionResults
ClangUserExpression::Execute (Stream &error_stream,
ExecutionContext &exe_ctx,
- bool unwind_on_error,
- bool ignore_breakpoints,
+ const EvaluateExpressionOptions& options,
ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
- lldb::ClangExpressionVariableSP &result,
- bool run_others,
- uint32_t timeout_usec)
+ lldb::ClangExpressionVariableSP &result)
{
// The expression log is quite verbose, and if you're just tracking the execution of the
// expression, it's quite convenient to have these logs come out with the STEP log as well.
@@ -856,9 +852,18 @@ ClangUserExpression::Execute (Stream &error_stream,
}
else
{
+ const uint32_t timeout_usec = options.GetTimeoutUsec();
+ const bool debug = options.GetDebug();
+ const bool unwind_on_error = debug ? false : options.DoesUnwindOnError();
+ const bool ignore_breakpoints = debug ? false : options.DoesIgnoreBreakpoints();
const bool stop_others = true;
- const bool try_all_threads = run_others;
-
+ const bool try_all_threads = options.GetRunOthers();
+ lldb::BreakpointSP debug_bkpt_sp;
+ if (debug)
+ {
+ // TODO: push this down into the thread plan and let the plan manage it
+ debug_bkpt_sp = exe_ctx.GetTargetRef().CreateBreakpoint(m_jit_start_addr, false, false);
+ }
Address wrapper_address (m_jit_start_addr);
lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
wrapper_address,
@@ -893,6 +898,11 @@ ClangUserExpression::Execute (Stream &error_stream,
timeout_usec,
error_stream);
+ if (debug_bkpt_sp)
+ {
+ exe_ctx.GetTargetRef().RemoveBreakpointByID(debug_bkpt_sp->GetID());
+ }
+
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
@@ -947,48 +957,17 @@ ClangUserExpression::Execute (Stream &error_stream,
ExecutionResults
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
- lldb_private::ExecutionPolicy execution_policy,
- lldb::LanguageType language,
- ResultType desired_type,
- bool unwind_on_error,
- bool ignore_breakpoints,
+ const EvaluateExpressionOptions& options,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp,
- bool run_others,
- uint32_t timeout_usec)
-{
- Error error;
- return EvaluateWithError (exe_ctx,
- execution_policy,
- language,
- desired_type,
- unwind_on_error,
- ignore_breakpoints,
- expr_cstr,
- expr_prefix,
- result_valobj_sp,
- error,
- run_others,
- timeout_usec);
-}
-
-ExecutionResults
-ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
- lldb_private::ExecutionPolicy execution_policy,
- lldb::LanguageType language,
- ResultType desired_type,
- bool unwind_on_error,
- bool ignore_breakpoints,
- const char *expr_cstr,
- const char *expr_prefix,
- lldb::ValueObjectSP &result_valobj_sp,
- Error &error,
- bool run_others,
- uint32_t timeout_usec)
+ Error &error)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+ 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;
Process *process = exe_ctx.GetProcessPtr();
@@ -1046,13 +1025,10 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
execution_results = user_expression_sp->Execute (error_stream,
- exe_ctx,
- unwind_on_error,
- ignore_breakpoints,
- user_expression_sp,
- expr_result,
- run_others,
- timeout_usec);
+ exe_ctx,
+ options,
+ user_expression_sp,
+ expr_result);
if (execution_results != eExecutionCompleted)
{
diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp
index e2ae19e5ac7f..b36be8e545d9 100644
--- a/source/Expression/DWARFExpression.cpp
+++ b/source/Expression/DWARFExpression.cpp
@@ -9,6 +9,10 @@
#include "lldb/Expression/DWARFExpression.h"
+// C Includes
+#include <inttypes.h>
+
+// C++ Includes
#include <vector>
#include "lldb/Core/DataEncoder.h"
@@ -28,20 +32,18 @@
#include "lldb/lldb-private-log.h"
-#include "lldb/Symbol/ClangASTType.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/Type.h"
-
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StackID.h"
+#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
+// TODO- why is this also defined (in a better way) in DWARFDefines.cpp?
const char *
DW_OP_value_to_name (uint32_t val)
{
@@ -220,6 +222,7 @@ DW_OP_value_to_name (uint32_t val)
// DWARFExpression constructor
//----------------------------------------------------------------------
DWARFExpression::DWARFExpression() :
+ m_module_wp(),
m_data(),
m_reg_kind (eRegisterKindDWARF),
m_loclist_slide (LLDB_INVALID_ADDRESS)
@@ -227,6 +230,7 @@ DWARFExpression::DWARFExpression() :
}
DWARFExpression::DWARFExpression(const DWARFExpression& rhs) :
+ m_module_wp(rhs.m_module_wp),
m_data(rhs.m_data),
m_reg_kind (rhs.m_reg_kind),
m_loclist_slide(rhs.m_loclist_slide)
@@ -234,11 +238,14 @@ DWARFExpression::DWARFExpression(const DWARFExpression& rhs) :
}
-DWARFExpression::DWARFExpression(const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length) :
+DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length) :
+ m_module_wp(),
m_data(data, data_offset, data_length),
m_reg_kind (eRegisterKindDWARF),
m_loclist_slide(LLDB_INVALID_ADDRESS)
{
+ if (module_sp)
+ m_module_wp = module_sp;
}
//----------------------------------------------------------------------
@@ -262,11 +269,12 @@ DWARFExpression::SetOpcodeData (const DataExtractor& data)
}
void
-DWARFExpression::CopyOpcodeData (const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length)
+DWARFExpression::CopyOpcodeData (lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length)
{
const uint8_t *bytes = data.PeekData(data_offset, data_length);
if (bytes)
{
+ m_module_wp = module_sp;
m_data.SetData(DataBufferSP(new DataBufferHeap(bytes, data_length)));
m_data.SetByteOrder(data.GetByteOrder());
m_data.SetAddressByteSize(data.GetAddressByteSize());
@@ -274,8 +282,9 @@ DWARFExpression::CopyOpcodeData (const DataExtractor& data, lldb::offset_t data_
}
void
-DWARFExpression::SetOpcodeData (const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length)
+DWARFExpression::SetOpcodeData (lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length)
{
+ m_module_wp = module_sp;
m_data.SetData(data, data_offset, data_length);
}
@@ -588,6 +597,9 @@ DWARFExpression::DumpLocation (Stream *s, lldb::offset_t offset, lldb::offset_t
// case DW_OP_APPLE_array_ref:
// s->PutCString("DW_OP_APPLE_array_ref");
// break;
+ case DW_OP_GNU_push_tls_address:
+ s->PutCString("DW_OP_GNU_push_tls_address"); // 0xe0
+ break;
case DW_OP_APPLE_uninit:
s->PutCString("DW_OP_APPLE_uninit"); // 0xF0
break;
@@ -919,7 +931,8 @@ GetOpcodeDataSize (const DataExtractor &data, const lldb::offset_t data_offset,
case DW_OP_form_tls_address: // 0x9b DWARF3
case DW_OP_call_frame_cfa: // 0x9c DWARF3
case DW_OP_stack_value: // 0x9f DWARF4
- return 0;
+ case DW_OP_GNU_push_tls_address: // 0xe0 GNU extension
+ return 0;
// Opcodes with a single 1 byte arguments
case DW_OP_const1u: // 0x08 1 1-byte constant
@@ -1221,6 +1234,8 @@ DWARFExpression::Evaluate
Error *error_ptr
) const
{
+ ModuleSP module_sp = m_module_wp.lock();
+
if (IsLocationList())
{
lldb::offset_t offset = 0;
@@ -1268,7 +1283,7 @@ DWARFExpression::Evaluate
if (length > 0 && lo_pc <= pc && pc < hi_pc)
{
- return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, m_data, offset, length, m_reg_kind, initial_value_ptr, result, error_ptr);
+ return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, offset, length, m_reg_kind, initial_value_ptr, result, error_ptr);
}
offset += length;
}
@@ -1280,7 +1295,7 @@ DWARFExpression::Evaluate
}
// Not a location list, just a single expression.
- return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, m_data, 0, m_data.GetByteSize(), m_reg_kind, initial_value_ptr, result, error_ptr);
+ return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, 0, m_data.GetByteSize(), m_reg_kind, initial_value_ptr, result, error_ptr);
}
@@ -1292,6 +1307,7 @@ DWARFExpression::Evaluate
ClangExpressionVariableList *expr_locals,
ClangExpressionDeclMap *decl_map,
RegisterContext *reg_ctx,
+ lldb::ModuleSP opcode_ctx,
const DataExtractor& opcodes,
const lldb::offset_t opcodes_offset,
const lldb::offset_t opcodes_length,
@@ -1347,7 +1363,7 @@ DWARFExpression::Evaluate
if (log && log->GetVerbose())
{
size_t count = stack.size();
- log->Printf("Stack before operation has %lu values:", count);
+ log->Printf("Stack before operation has %zu values:", count);
for (size_t i=0; i<count; ++i)
{
StreamString new_value;
@@ -2659,6 +2675,54 @@ DWARFExpression::Evaluate
return false;
}
break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_GNU_push_tls_address
+ // OPERANDS: none
+ // DESCRIPTION: Pops a TLS offset from the stack, converts it to
+ // an absolute value, and pushes it back on.
+ //----------------------------------------------------------------------
+ case DW_OP_GNU_push_tls_address:
+ {
+ if (stack.size() < 1)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString("DW_OP_GNU_push_tls_address needs an argument.");
+ return false;
+ }
+
+ if (!exe_ctx || !opcode_ctx)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString("No context to evaluate TLS within.");
+ return false;
+ }
+
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (!thread)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString("No thread to evaluate TLS within.");
+ return false;
+ }
+
+ // Lookup the TLS block address for this thread and module.
+ addr_t tls_addr = thread->GetThreadLocalData (opcode_ctx);
+
+ if (tls_addr == LLDB_INVALID_ADDRESS)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString ("No TLS data currently exists for this thread.");
+ return false;
+ }
+
+ // Convert the TLS offset into the absolute address.
+ Scalar tmp = stack.back().ResolveValue(exe_ctx);
+ stack.back() = tmp + tls_addr;
+ stack.back().SetValueType (Value::eValueTypeLoadAddress);
+ }
+ break;
+
default:
if (log)
log->Printf("Unhandled opcode %s in DWARFExpression.", DW_OP_value_to_name(op));
@@ -2675,7 +2739,7 @@ DWARFExpression::Evaluate
else if (log && log->GetVerbose())
{
size_t count = stack.size();
- log->Printf("Stack after operation has %lu values:", count);
+ log->Printf("Stack after operation has %zu values:", count);
for (size_t i=0; i<count; ++i)
{
StreamString new_value;
diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp
index 16ef6e5d54e1..104732a283c2 100644
--- a/source/Expression/IRExecutionUnit.cpp
+++ b/source/Expression/IRExecutionUnit.cpp
@@ -490,11 +490,12 @@ IRExecutionUnit::MemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
uint8_t *
IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size,
unsigned Alignment,
- unsigned SectionID)
+ unsigned SectionID,
+ llvm::StringRef SectionName)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID);
+ 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,
@@ -515,11 +516,12 @@ uint8_t *
IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size,
unsigned Alignment,
unsigned SectionID,
+ llvm::StringRef SectionName,
bool IsReadOnly)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, IsReadOnly);
+ 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,
diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp
index cac3fdf60dfa..d68dc002a5a5 100644
--- a/source/Expression/IRForTarget.cpp
+++ b/source/Expression/IRForTarget.cpp
@@ -361,8 +361,8 @@ IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module)
// 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(Attribute::NoBuiltin)) {
- Attribute builtin = Attribute::get(fun->getContext(), Attribute::Builtin);
+ 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)) {
@@ -2028,7 +2028,7 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
}
ss.flush();
- log->Printf("Found ConstantFP with size %lu and raw data %s", operand_data_size, s.c_str());
+ log->Printf("Found ConstantFP with size %zu and raw data %s", operand_data_size, s.c_str());
}
lldb_private::DataBufferHeap data(operand_data_size, 0);
@@ -2491,7 +2491,7 @@ IRForTarget::ReplaceVariables (Function &llvm_function)
}
if (log)
- log->Printf("Total structure [align %" PRId64 ", size %lu]", alignment, size);
+ log->Printf("Total structure [align %" PRId64 ", size %zu]", alignment, size);
return true;
}
diff --git a/source/Expression/IRInterpreter.cpp b/source/Expression/IRInterpreter.cpp
index dcbf584cfb63..71ef8d6457bc 100644
--- a/source/Expression/IRInterpreter.cpp
+++ b/source/Expression/IRInterpreter.cpp
@@ -14,6 +14,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Host/Endian.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
@@ -321,13 +322,19 @@ public:
if (!ResolveConstantValue(resolved_value, constant))
return false;
- const uint64_t *raw_data = resolved_value.getRawData();
-
+ 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, (uint8_t*)raw_data, constant_size, write_error);
+ m_memory_map.WriteMemory(process_address, (const uint8_t*)buffer.GetData(), constant_size, write_error);
return write_error.Success();
}
@@ -517,6 +524,7 @@ IRInterpreter::CanInterpret (llvm::Module &module,
case Instruction::SRem:
case Instruction::Store:
case Instruction::Sub:
+ case Instruction::Trunc:
case Instruction::UDiv:
case Instruction::URem:
case Instruction::Xor:
@@ -1162,6 +1170,42 @@ IRInterpreter::Interpret (llvm::Module &module,
}
}
break;
+ case Instruction::Trunc:
+ {
+ const TruncInst *trunc_inst = dyn_cast<TruncInst>(inst);
+
+ if (!trunc_inst)
+ {
+ if (log)
+ log->Printf("getOpcode() returns Trunc, but instruction is not a TruncInst");
+ error.SetErrorToGenericError();
+ 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)
+ log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ frame.AssignValue(inst, I, module);
+
+ if (log)
+ {
+ log->Printf("Interpreted a Trunc");
+ log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str());
+ log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
+ }
+ }
+ break;
case Instruction::Load:
{
const LoadInst *load_inst = dyn_cast<LoadInst>(inst);
diff --git a/source/Expression/IRMemoryMap.cpp b/source/Expression/IRMemoryMap.cpp
index ef362baff161..53f74aebfed1 100644
--- a/source/Expression/IRMemoryMap.cpp
+++ b/source/Expression/IRMemoryMap.cpp
@@ -74,15 +74,15 @@ IRMemoryMap::FindSpace (size_t size)
{
case 4:
{
- uint32_t random_data = random();
+ uint32_t random_data = rand();
candidate = random_data;
candidate &= ~0xfffull;
break;
}
case 8:
{
- uint32_t random_low = random();
- uint32_t random_high = random();
+ uint32_t random_low = rand();
+ uint32_t random_high = rand();
candidate = random_high;
candidate <<= 32ull;
candidate |= random_low;
diff --git a/source/Expression/Materializer.cpp b/source/Expression/Materializer.cpp
index 8a1900ebb739..fb9522f0dc36 100644
--- a/source/Expression/Materializer.cpp
+++ b/source/Expression/Materializer.cpp
@@ -461,17 +461,11 @@ public:
}
else
{
- Error get_address_error;
- lldb::ValueObjectSP addr_of_valobj_sp = valobj_sp->AddressOf(get_address_error);
- if (get_address_error.Success())
+ lldb::addr_t addr_of_valobj = valobj_sp->GetAddressOf();
+ if (addr_of_valobj != LLDB_INVALID_ADDRESS)
{
- DataExtractor valobj_extractor;
- addr_of_valobj_sp->GetData(valobj_extractor);
- lldb::offset_t offset = 0;
- lldb::addr_t addr_of_valobj_addr = valobj_extractor.GetAddress(&offset);
-
Error write_error;
- map.WritePointerToMemory(load_addr, addr_of_valobj_addr, write_error);
+ map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
if (!write_error.Success())
{
@@ -839,7 +833,7 @@ public:
name,
address,
eAddressTypeLoad,
- ret->GetByteSize());
+ map.GetAddressByteSize());
}
ret->ValueUpdated();
diff --git a/source/Host/common/Condition.cpp b/source/Host/common/Condition.cpp
index daa729cadca5..7bc6b6554648 100644
--- a/source/Host/common/Condition.cpp
+++ b/source/Host/common/Condition.cpp
@@ -15,6 +15,8 @@
using namespace lldb_private;
+#ifndef _WIN32
+
//----------------------------------------------------------------------
// Default constructor
//
@@ -47,15 +49,6 @@ Condition::Broadcast ()
}
//----------------------------------------------------------------------
-// Get accessor to the pthread condition object
-//----------------------------------------------------------------------
-pthread_cond_t *
-Condition::GetCondition ()
-{
- return &m_condition;
-}
-
-//----------------------------------------------------------------------
// Unblocks one thread waiting for the condition variable
//----------------------------------------------------------------------
int
@@ -64,6 +57,11 @@ 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
@@ -100,7 +98,16 @@ Condition::Wait (Mutex &mutex, const TimeValue *abstime, bool *timed_out)
*timed_out = false;
}
-
return err;
}
+#endif
+
+//----------------------------------------------------------------------
+// Get accessor to the pthread condition object
+//----------------------------------------------------------------------
+lldb::condition_t *
+Condition::GetCondition()
+{
+ return &m_condition;
+}
diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp
index c0d3c290f4c7..addd43515405 100644
--- a/source/Host/common/File.cpp
+++ b/source/Host/common/File.cpp
@@ -16,6 +16,10 @@
#include <stdarg.h>
#include <sys/stat.h>
+#ifdef _WIN32
+#include "lldb/Host/windows/windows.h"
+#endif
+
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/Config.h"
@@ -79,6 +83,20 @@ File::File(const char *path, uint32_t options, uint32_t permissions) :
Open (path, options, permissions);
}
+File::File (const FileSpec& filespec,
+ uint32_t options,
+ uint32_t permissions) :
+ m_descriptor (kInvalidDescriptor),
+ m_stream (kInvalidStream),
+ m_options (0),
+ m_owned (false)
+{
+ if (filespec)
+ {
+ Open (filespec.GetPath().c_str(), options, permissions);
+ }
+}
+
File::File (const File &rhs) :
m_descriptor (kInvalidDescriptor),
m_stream (kInvalidStream),
@@ -167,7 +185,11 @@ File::Duplicate (const File &rhs)
if (rhs.DescriptorIsValid())
{
+#ifdef _WIN32
+ m_descriptor = ::_dup(rhs.GetDescriptor());
+#else
m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD);
+#endif
if (!DescriptorIsValid())
error.SetErrorToErrno();
else
@@ -217,8 +239,12 @@ File::Open (const char *path, uint32_t options, uint32_t permissions)
oflag |= O_RDONLY;
}
+#ifndef _WIN32
if (options & eOpenOptionNonBlocking)
oflag |= O_NONBLOCK;
+#else
+ oflag |= O_BINARY;
+#endif
mode_t mode = 0;
if (oflag & O_CREAT)
@@ -247,6 +273,53 @@ File::Open (const char *path, uint32_t options, uint32_t permissions)
return error;
}
+uint32_t
+File::GetPermissions (const char *path, Error &error)
+{
+ if (path && path[0])
+ {
+ struct stat file_stats;
+ if (::stat (path, &file_stats) == -1)
+ error.SetErrorToErrno();
+ else
+ {
+ error.Clear();
+ return file_stats.st_mode; // All bits from lldb_private::File::Permissions match those in POSIX mode bits
+ }
+ }
+ else
+ {
+ if (path)
+ error.SetErrorString ("invalid path");
+ else
+ error.SetErrorString ("empty path");
+ }
+ return 0;
+}
+
+uint32_t
+File::GetPermissions(Error &error) const
+{
+ int fd = GetDescriptor();
+ if (fd != kInvalidDescriptor)
+ {
+ struct stat file_stats;
+ if (::fstat (fd, &file_stats) == -1)
+ error.SetErrorToErrno();
+ else
+ {
+ error.Clear();
+ return file_stats.st_mode; // All bits from lldb_private::File::Permissions match those in POSIX mode bits
+ }
+ }
+ else
+ {
+ error.SetErrorString ("invalid file descriptor");
+ }
+ return 0;
+}
+
+
Error
File::Close ()
{
@@ -452,6 +525,11 @@ File::Sync ()
Error error;
if (DescriptorIsValid())
{
+#ifdef _WIN32
+ int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
+ if (err == 0)
+ error.SetErrorToGenericError();
+#else
int err = 0;
do
{
@@ -460,6 +538,7 @@ File::Sync ()
if (err == -1)
error.SetErrorToErrno();
+#endif
}
else
{
@@ -559,6 +638,7 @@ File::Write (const void *buf, size_t &num_bytes)
Error
File::Read (void *buf, size_t &num_bytes, off_t &offset)
{
+#ifndef _WIN32
Error error;
int fd = GetDescriptor();
if (fd != kInvalidDescriptor)
@@ -586,6 +666,14 @@ File::Read (void *buf, size_t &num_bytes, off_t &offset)
error.SetErrorString("invalid file handle");
}
return error;
+#else
+ long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
+ SeekFromStart(offset);
+ Error error = Read(buf, num_bytes);
+ if (!error.Fail())
+ SeekFromStart(cur);
+ return error;
+#endif
}
Error
@@ -648,6 +736,7 @@ File::Write (const void *buf, size_t &num_bytes, off_t &offset)
int fd = GetDescriptor();
if (fd != kInvalidDescriptor)
{
+#ifndef _WIN32
ssize_t bytes_written = -1;
do
{
@@ -664,6 +753,17 @@ File::Write (const void *buf, size_t &num_bytes, off_t &offset)
offset += bytes_written;
num_bytes = bytes_written;
}
+#else
+ long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
+ error = Write(buf, num_bytes);
+ long after = ::lseek(m_descriptor, 0, SEEK_CUR);
+
+ if (!error.Fail())
+ SeekFromStart(cur);
+
+ ssize_t bytes_written = after - cur;
+ offset = after;
+#endif
}
else
{
@@ -714,3 +814,29 @@ File::PrintfVarArg (const char *format, va_list args)
}
return result;
}
+
+mode_t
+File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
+{
+ mode_t mode = 0;
+ if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
+ mode |= O_RDWR;
+ else if (open_options & eOpenOptionWrite)
+ mode |= O_WRONLY;
+
+ if (open_options & eOpenOptionAppend)
+ mode |= O_APPEND;
+
+ if (open_options & eOpenOptionTruncate)
+ mode |= O_TRUNC;
+
+ if (open_options & eOpenOptionNonBlocking)
+ mode |= O_NONBLOCK;
+
+ if (open_options & eOpenOptionCanCreateNewOnly)
+ mode |= O_CREAT | O_EXCL;
+ else if (open_options & eOpenOptionCanCreate)
+ mode |= O_CREAT;
+
+ return mode;
+}
diff --git a/source/Host/common/FileSpec.cpp b/source/Host/common/FileSpec.cpp
index 08d626e836a1..33de198072dc 100644
--- a/source/Host/common/FileSpec.cpp
+++ b/source/Host/common/FileSpec.cpp
@@ -8,9 +8,15 @@
//===----------------------------------------------------------------------===//
+#ifndef _WIN32
#include <dirent.h>
+#else
+#include "lldb/Host/windows/windows.h"
+#endif
#include <fcntl.h>
+#ifndef _MSC_VER
#include <libgen.h>
+#endif
#include <sys/stat.h>
#include <set>
#include <string.h>
@@ -25,6 +31,7 @@
#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/Core/DataBufferHeap.h"
@@ -323,7 +330,11 @@ FileSpec::SetFile (const char *pathname, bool resolve)
// 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, '/'))
+ if (strchr(resolved_path, '/')
+#ifdef _WIN32
+ || strchr(resolved_path, '\\')
+#endif
+ )
{
char *directory = ::dirname (resolved_path);
@@ -334,6 +345,11 @@ FileSpec::SetFile (const char *pathname, bool resolve)
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';
@@ -616,10 +632,12 @@ FileSpec::GetFileType () const
switch (file_type)
{
case S_IFDIR: return eFileTypeDirectory;
- case S_IFIFO: return eFileTypePipe;
case S_IFREG: return eFileTypeRegular;
+#ifndef _WIN32
+ case S_IFIFO: return eFileTypePipe;
case S_IFSOCK: return eFileTypeSocket;
case S_IFLNK: return eFileTypeSymbolicLink;
+#endif
default:
break;
}
@@ -907,7 +925,94 @@ FileSpec::EnumerateDirectory
{
if (dir_path && dir_path[0])
{
- lldb_utility::CleanUp <DIR *, int> dir_path_dir (opendir(dir_path), NULL, closedir);
+#if _WIN32
+ char szDir[MAX_PATH];
+ strcpy_s(szDir, MAX_PATH, dir_path);
+ strcat_s(szDir, MAX_PATH, "\\*");
+
+ WIN32_FIND_DATA ffd;
+ HANDLE hFind = FindFirstFile(szDir, &ffd);
+
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ return eEnumerateDirectoryResultNext;
+ }
+
+ do
+ {
+ bool call_callback = false;
+ FileSpec::FileType file_type = eFileTypeUnknown;
+ if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ size_t len = strlen(ffd.cFileName);
+
+ if (len == 1 && ffd.cFileName[0] == '.')
+ continue;
+
+ if (len == 2 && ffd.cFileName[0] == '.' && ffd.cFileName[1] == '.')
+ continue;
+
+ file_type = eFileTypeDirectory;
+ call_callback = find_directories;
+ }
+ else if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE)
+ {
+ file_type = eFileTypeOther;
+ call_callback = find_other;
+ }
+ else
+ {
+ file_type = eFileTypeRegular;
+ call_callback = find_files;
+ }
+ if (call_callback)
+ {
+ char child_path[MAX_PATH];
+ const int child_path_len = ::snprintf (child_path, sizeof(child_path), "%s\\%s", dir_path, ffd.cFileName);
+ if (child_path_len < (int)(sizeof(child_path) - 1))
+ {
+ // Don't resolve the file type or path
+ FileSpec child_path_spec (child_path, false);
+
+ EnumerateDirectoryResult result = callback (callback_baton, file_type, child_path_spec);
+
+ switch (result)
+ {
+ case eEnumerateDirectoryResultNext:
+ // Enumerate next entry in the current directory. We just
+ // exit this switch and will continue enumerating the
+ // current directory as we currently are...
+ break;
+
+ case eEnumerateDirectoryResultEnter: // Recurse into the current entry if it is a directory or symlink, or next if not
+ if (FileSpec::EnumerateDirectory(child_path,
+ find_directories,
+ find_files,
+ find_other,
+ callback,
+ callback_baton) == eEnumerateDirectoryResultQuit)
+ {
+ // The subdirectory returned Quit, which means to
+ // stop all directory enumerations at all levels.
+ return eEnumerateDirectoryResultQuit;
+ }
+ break;
+
+ case eEnumerateDirectoryResultExit: // Exit from the current directory at the current level.
+ // Exit from this directory level and tell parent to
+ // keep enumerating.
+ return eEnumerateDirectoryResultNext;
+
+ case eEnumerateDirectoryResultQuit: // Stop directory enumerations at any level
+ return eEnumerateDirectoryResultQuit;
+ }
+ }
+ }
+ } while (FindNextFile(hFind, &ffd) != 0);
+
+ FindClose(hFind);
+#else
+ lldb_utility::CleanUp <DIR *, int> dir_path_dir(opendir(dir_path), NULL, closedir);
if (dir_path_dir.is_valid())
{
long path_max = fpathconf (dirfd (dir_path_dir.get()), _PC_NAME_MAX);
@@ -1006,12 +1111,147 @@ FileSpec::EnumerateDirectory
free (buf);
}
}
+#endif
}
// By default when exiting a directory, we tell the parent enumeration
// to continue enumerating.
return eEnumerateDirectoryResultNext;
}
+FileSpec
+FileSpec::CopyByAppendingPathComponent (const char *new_path) const
+{
+ const bool resolve = false;
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ return FileSpec(new_path,resolve);
+ StreamString stream;
+ if (m_filename.IsEmpty())
+ stream.Printf("%s/%s",m_directory.GetCString(),new_path);
+ else if (m_directory.IsEmpty())
+ stream.Printf("%s/%s",m_filename.GetCString(),new_path);
+ else
+ stream.Printf("%s/%s/%s",m_directory.GetCString(), m_filename.GetCString(),new_path);
+ return FileSpec(stream.GetData(),resolve);
+}
+
+FileSpec
+FileSpec::CopyByRemovingLastPathComponent () const
+{
+ const bool resolve = false;
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ return FileSpec("",resolve);
+ if (m_directory.IsEmpty())
+ return FileSpec("",resolve);
+ if (m_filename.IsEmpty())
+ {
+ const char* dir_cstr = m_directory.GetCString();
+ const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
+
+ // check for obvious cases before doing the full thing
+ if (!last_slash_ptr)
+ return FileSpec("",resolve);
+ if (last_slash_ptr == dir_cstr)
+ return FileSpec("/",resolve);
+
+ size_t last_slash_pos = last_slash_ptr - dir_cstr+1;
+ ConstString new_path(dir_cstr,last_slash_pos);
+ return FileSpec(new_path.GetCString(),resolve);
+ }
+ else
+ return FileSpec(m_directory.GetCString(),resolve);
+}
+
+const char*
+FileSpec::GetLastPathComponent () const
+{
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ return NULL;
+ if (m_filename.IsEmpty())
+ {
+ const char* dir_cstr = m_directory.GetCString();
+ const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
+ if (last_slash_ptr == NULL)
+ return m_directory.GetCString();
+ if (last_slash_ptr == dir_cstr)
+ {
+ if (last_slash_ptr[1] == 0)
+ return last_slash_ptr;
+ else
+ return last_slash_ptr+1;
+ }
+ if (last_slash_ptr[1] != 0)
+ return last_slash_ptr+1;
+ const char* penultimate_slash_ptr = last_slash_ptr;
+ while (*penultimate_slash_ptr)
+ {
+ --penultimate_slash_ptr;
+ if (penultimate_slash_ptr == dir_cstr)
+ break;
+ if (*penultimate_slash_ptr == '/')
+ break;
+ }
+ ConstString new_path(penultimate_slash_ptr+1,last_slash_ptr-penultimate_slash_ptr);
+ return new_path.AsCString();
+ }
+ return m_filename.GetCString();
+}
+
+void
+FileSpec::AppendPathComponent (const char *new_path)
+{
+ const bool resolve = false;
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ {
+ SetFile(new_path,resolve);
+ return;
+ }
+ StreamString stream;
+ if (m_filename.IsEmpty())
+ stream.Printf("%s/%s",m_directory.GetCString(),new_path);
+ else if (m_directory.IsEmpty())
+ stream.Printf("%s/%s",m_filename.GetCString(),new_path);
+ else
+ stream.Printf("%s/%s/%s",m_directory.GetCString(), m_filename.GetCString(),new_path);
+ SetFile(stream.GetData(), resolve);
+}
+
+void
+FileSpec::RemoveLastPathComponent ()
+{
+ const bool resolve = false;
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ {
+ SetFile("",resolve);
+ return;
+ }
+ if (m_directory.IsEmpty())
+ {
+ SetFile("",resolve);
+ return;
+ }
+ if (m_filename.IsEmpty())
+ {
+ const char* dir_cstr = m_directory.GetCString();
+ const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
+
+ // check for obvious cases before doing the full thing
+ if (!last_slash_ptr)
+ {
+ SetFile("",resolve);
+ return;
+ }
+ if (last_slash_ptr == dir_cstr)
+ {
+ SetFile("/",resolve);
+ return;
+ }
+ size_t last_slash_pos = last_slash_ptr - dir_cstr+1;
+ ConstString new_path(dir_cstr,last_slash_pos);
+ SetFile(new_path.GetCString(),resolve);
+ }
+ else
+ SetFile(m_directory.GetCString(),resolve);
+}
//------------------------------------------------------------------
/// Returns true if the filespec represents an implementation source
/// file (files with a ".c", ".cpp", ".m", ".mm" (many more)
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp
index a7bad0063efd..296e4b40bf01 100644
--- a/source/Host/common/Host.cpp
+++ b/source/Host/common/Host.cpp
@@ -10,26 +10,33 @@
#include "lldb/lldb-python.h"
// C includes
-#include <dlfcn.h>
#include <errno.h>
-#include <grp.h>
#include <limits.h>
+#include <sys/types.h>
+#ifdef _WIN32
+#include "lldb/Host/windows/windows.h"
+#include <winsock2.h>
+#include <WS2tcpip.h>
+#else
+#include <dlfcn.h>
+#include <grp.h>
#include <netdb.h>
#include <pwd.h>
-#include <sys/types.h>
+#endif
+
+#if !defined (__GNU__) && !defined (_WIN32)
+// Does not exist under GNU/HURD or Windows
#include <sys/sysctl.h>
-#include <unistd.h>
+#endif
#if defined (__APPLE__)
-
-#include <dispatch/dispatch.h>
-#include <libproc.h>
-#include <mach-o/dyld.h>
#include <mach/mach_port.h>
-
+#include <mach/mach_init.h>
+#include <mach-o/dyld.h>
#endif
#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
+#include <spawn.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#endif
@@ -44,6 +51,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ThreadSafeSTLMap.h"
#include "lldb/Host/Config.h"
@@ -52,21 +60,18 @@
#include "lldb/Host/Mutex.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/TargetList.h"
+#include "lldb/Utility/CleanUp.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/MachO.h"
#include "llvm/Support/raw_ostream.h"
-
-
-
using namespace lldb;
using namespace lldb_private;
-#if !defined (__APPLE__)
+#if !defined (__APPLE__) && !defined (_WIN32)
struct MonitorInfo
{
lldb::pid_t pid; // The process ID to monitor
@@ -75,7 +80,7 @@ struct MonitorInfo
bool monitor_signals; // If true, call the callback when "pid" gets signaled.
};
-static void *
+static thread_result_t
MonitorChildProcessThreadFunction (void *arg);
lldb::thread_t
@@ -89,7 +94,7 @@ Host::StartMonitoringChildProcess
{
lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
MonitorInfo * info_ptr = new MonitorInfo();
-
+
info_ptr->pid = pid;
info_ptr->callback = callback;
info_ptr->callback_baton = callback_baton;
@@ -133,7 +138,7 @@ private:
int m_old_state; // Save the old cancelability state.
};
-static void *
+static thread_result_t
MonitorChildProcessThreadFunction (void *arg)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
@@ -145,9 +150,11 @@ MonitorChildProcessThreadFunction (void *arg)
const Host::MonitorChildProcessCallback callback = info->callback;
void * const callback_baton = info->callback_baton;
- const lldb::pid_t pid = info->pid;
const bool monitor_signals = info->monitor_signals;
+ assert (info->pid <= UINT32_MAX);
+ const ::pid_t pid = monitor_signals ? -1 * info->pid : info->pid;
+
delete info;
int status = -1;
@@ -160,12 +167,12 @@ MonitorChildProcessThreadFunction (void *arg)
{
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
if (log)
- log->Printf("%s ::wait_pid (pid = %" PRIu64 ", &status, options = %i)...", function, pid, options);
+ log->Printf("%s ::wait_pid (pid = %" PRIi32 ", &status, options = %i)...", function, pid, options);
// Wait for all child processes
::pthread_testcancel ();
// Get signals from all children with same process group of pid
- const lldb::pid_t wait_pid = ::waitpid (-1*pid, &status, options);
+ const ::pid_t wait_pid = ::waitpid (pid, &status, options);
::pthread_testcancel ();
if (wait_pid == -1)
@@ -200,7 +207,7 @@ MonitorChildProcessThreadFunction (void *arg)
{
signal = WTERMSIG(status);
status_cstr = "SIGNALED";
- if (wait_pid == pid) {
+ if (wait_pid == abs(pid)) {
exited = true;
exit_status = -1;
}
@@ -216,7 +223,7 @@ MonitorChildProcessThreadFunction (void *arg)
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
if (log)
- log->Printf ("%s ::waitpid (pid = %" PRIu64 ", &status, options = %i) => pid = %" PRIu64 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i",
+ log->Printf ("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i) => pid = %" PRIi32 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i",
function,
wait_pid,
options,
@@ -233,7 +240,7 @@ MonitorChildProcessThreadFunction (void *arg)
callback_return = callback (callback_baton, wait_pid, exited, signal, exit_status);
// If our process exited, then this thread should exit
- if (exited && wait_pid == pid)
+ if (exited && wait_pid == abs(pid))
{
if (log)
log->Printf ("%s (arg = %p) thread exiting because pid received exit signal...", __FUNCTION__, arg);
@@ -259,6 +266,9 @@ MonitorChildProcessThreadFunction (void *arg)
return NULL;
}
+#endif // #if !defined (__APPLE__) && !defined (_WIN32)
+
+#if !defined (__APPLE__)
void
Host::SystemLog (SystemLogType type, const char *format, va_list args)
@@ -266,7 +276,7 @@ Host::SystemLog (SystemLogType type, const char *format, va_list args)
vfprintf (stderr, format, args);
}
-#endif // #if !defined (__APPLE__)
+#endif
void
Host::SystemLog (SystemLogType type, const char *format, ...)
@@ -277,12 +287,6 @@ Host::SystemLog (SystemLogType type, const char *format, ...)
va_end (args);
}
-size_t
-Host::GetPageSize()
-{
- return ::getpagesize();
-}
-
const ArchSpec &
Host::GetArchitecture (SystemDefaultArchitecture arch_kind)
{
@@ -445,6 +449,8 @@ Host::GetCurrentProcessID()
return ::getpid();
}
+#ifndef _WIN32
+
lldb::tid_t
Host::GetCurrentThreadID()
{
@@ -521,6 +527,8 @@ Host::GetSignalAsCString (int signo)
return NULL;
}
+#endif
+
void
Host::WillTerminate ()
{
@@ -563,6 +571,9 @@ struct HostThreadCreateInfo
};
static thread_result_t
+#ifdef _WIN32
+__stdcall
+#endif
ThreadCreateTrampoline (thread_arg_t arg)
{
HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg;
@@ -592,7 +603,12 @@ Host::ThreadCreate
// Host::ThreadCreateTrampoline will delete this pointer for us.
HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg);
+#ifdef _WIN32
+ thread = ::_beginthreadex(0, 0, ThreadCreateTrampoline, info_ptr, 0, NULL);
+ int err = thread <= 0 ? GetLastError() : 0;
+#else
int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr);
+#endif
if (err == 0)
{
if (error)
@@ -606,6 +622,8 @@ Host::ThreadCreate
return LLDB_INVALID_HOST_THREAD;
}
+#ifndef _WIN32
+
bool
Host::ThreadCancel (lldb::thread_t thread, Error *error)
{
@@ -633,6 +651,26 @@ Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Err
return err == 0;
}
+lldb::thread_key_t
+Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback)
+{
+ pthread_key_t key;
+ ::pthread_key_create (&key, callback);
+ return key;
+}
+
+void*
+Host::ThreadLocalStorageGet(lldb::thread_key_t key)
+{
+ return ::pthread_getspecific (key);
+}
+
+void
+Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value)
+{
+ ::pthread_setspecific (key, value);
+}
+
bool
Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name)
{
@@ -723,9 +761,13 @@ Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid,
}
return Host::SetThreadName (pid, tid, namebuf);
}
+
+ ::free(namebuf);
return false;
}
+#endif
+
FileSpec
Host::GetProgramFileSpec ()
{
@@ -771,19 +813,6 @@ Host::GetProgramFileSpec ()
return g_program_filespec;
}
-FileSpec
-Host::GetModuleFileSpecForHostAddress (const void *host_addr)
-{
- FileSpec module_filespec;
- Dl_info info;
- if (::dladdr (host_addr, &info))
- {
- if (info.dli_fname)
- module_filespec.SetFile(info.dli_fname, true);
- }
- return module_filespec;
-}
-
#if !defined (__APPLE__) // see Host.mm
bool
@@ -800,6 +829,8 @@ Host::ResolveExecutableInBundle (FileSpec &file)
}
#endif
+#ifndef _WIN32
+
// Opaque info that tracks a dynamic library that was loaded
struct DynamicLibraryInfo
{
@@ -924,6 +955,21 @@ Host::DynamicLibraryGetSymbol (void *opaque, const char *symbol_name, Error &err
return NULL;
}
+FileSpec
+Host::GetModuleFileSpecForHostAddress (const void *host_addr)
+{
+ FileSpec module_filespec;
+ Dl_info info;
+ if (::dladdr (host_addr, &info))
+ {
+ if (info.dli_fname)
+ module_filespec.SetFile(info.dli_fname, true);
+ }
+ return module_filespec;
+}
+
+#endif
+
bool
Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
{
@@ -944,7 +990,7 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
g_lldb_so_dir = lldb_file_spec.GetDirectory();
}
file_spec.GetDirectory() = g_lldb_so_dir;
- return file_spec.GetDirectory();
+ return (bool)file_spec.GetDirectory();
}
break;
@@ -975,7 +1021,7 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
}
}
file_spec.GetDirectory() = g_lldb_support_exe_dir;
- return file_spec.GetDirectory();
+ return (bool)file_spec.GetDirectory();
}
break;
@@ -1007,12 +1053,15 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
#endif
}
file_spec.GetDirectory() = g_lldb_headers_dir;
- return file_spec.GetDirectory();
+ return (bool)file_spec.GetDirectory();
}
break;
-#ifndef LLDB_DISABLE_PYTHON
- case ePathTypePythonDir:
+#ifdef LLDB_DISABLE_PYTHON
+ case ePathTypePythonDir:
+ return false;
+#else
+ case ePathTypePythonDir:
{
static ConstString g_lldb_python_dir;
if (!g_lldb_python_dir)
@@ -1049,7 +1098,7 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
}
}
file_spec.GetDirectory() = g_lldb_python_dir;
- return file_spec.GetDirectory();
+ return (bool)file_spec.GetDirectory();
}
break;
#endif
@@ -1116,7 +1165,7 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
}
}
file_spec.GetDirectory() = g_lldb_user_plugin_dir;
- return file_spec.GetDirectory();
+ return (bool)file_spec.GetDirectory();
#elif defined (__linux__)
static ConstString g_lldb_user_plugin_dir;
if (!g_lldb_user_plugin_dir)
@@ -1147,7 +1196,7 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
g_lldb_user_plugin_dir.SetCString(lldb_file_spec.GetPath().c_str());
}
file_spec.GetDirectory() = g_lldb_user_plugin_dir;
- return file_spec.GetDirectory();
+ return (bool)file_spec.GetDirectory();
#endif
// TODO: where would user LLDB plug-ins be located on other systems?
return false;
@@ -1175,6 +1224,8 @@ Host::GetHostname (std::string &s)
return false;
}
+#ifndef _WIN32
+
const char *
Host::GetUserName (uint32_t uid, std::string &user_name)
{
@@ -1234,22 +1285,6 @@ Host::GetGroupName (uint32_t gid, std::string &group_name)
return NULL;
}
-#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
-
uint32_t
Host::GetUserID ()
{
@@ -1274,16 +1309,32 @@ Host::GetEffectiveGroupID ()
return getegid();
}
-#if !defined (__APPLE__) && !defined(__linux__)
+#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();
}
-#endif // #if !defined (__APPLE__) && !defined(__linux__)
-#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined(__linux__)
bool
Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
@@ -1386,7 +1437,8 @@ Host::RunShellCommand (const char *command,
launch_info.ConvertArgumentsForLaunchingInShell (error,
localhost,
will_debug,
- first_arg_is_full_shell_command);
+ first_arg_is_full_shell_command,
+ 0);
}
else
{
@@ -1425,23 +1477,31 @@ Host::RunShellCommand (const char *command,
error = LaunchProcess (launch_info);
const lldb::pid_t pid = launch_info.GetProcessID();
- if (pid != LLDB_INVALID_PROCESS_ID)
+
+ if (error.Success() && pid == LLDB_INVALID_PROCESS_ID)
+ error.SetErrorString("failed to get process ID");
+
+ if (error.Success())
{
// The process successfully launched, so we can defer ownership of
// "shell_info" to the MonitorShellCommand callback function that will
// get called when the process dies. We release the unique pointer as it
// doesn't need to delete the ShellInfo anymore.
ShellInfo *shell_info = shell_info_ap.release();
+ TimeValue *timeout_ptr = nullptr;
TimeValue timeout_time(TimeValue::Now());
- timeout_time.OffsetWithSeconds(timeout_sec);
+ if (timeout_sec > 0) {
+ timeout_time.OffsetWithSeconds(timeout_sec);
+ timeout_ptr = &timeout_time;
+ }
bool timed_out = false;
- shell_info->process_reaped.WaitForValueEqualTo(true, &timeout_time, &timed_out);
+ shell_info->process_reaped.WaitForValueEqualTo(true, timeout_ptr, &timed_out);
if (timed_out)
{
error.SetErrorString("timed out waiting for shell command to complete");
-
+
// Kill the process since it didn't complete withint the timeout specified
- ::kill (pid, SIGKILL);
+ Kill (pid, SIGKILL);
// Wait for the monitor callback to get the message
timeout_time = TimeValue::Now();
timeout_time.OffsetWithSeconds(1);
@@ -1477,10 +1537,6 @@ Host::RunShellCommand (const char *command,
}
shell_info->can_delete.SetValue(true, eBroadcastAlways);
}
- else
- {
- error.SetErrorString("failed to get process ID");
- }
if (output_file_path)
::unlink (output_file_path);
@@ -1490,6 +1546,212 @@ Host::RunShellCommand (const char *command,
return error;
}
+#if defined(__linux__) or defined(__FreeBSD__)
+// The functions below implement process launching via posix_spawn() for Linux
+// and FreeBSD.
+
+// The posix_spawn() and posix_spawnp() functions first appeared in FreeBSD 8.0,
+static Error
+LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid)
+{
+ Error error;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
+
+ assert(exe_path);
+ assert(!launch_info.GetFlags().Test (eLaunchFlagDebug));
+
+ posix_spawnattr_t attr;
+
+ error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
+ error.LogIfError(log, "::posix_spawnattr_init ( &attr )");
+ if (error.Fail())
+ return error;
+
+ // Make a quick class that will cleanup the posix spawn attributes in case
+ // we return in the middle of this function.
+ lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy);
+
+ sigset_t no_signals;
+ sigset_t all_signals;
+ sigemptyset (&no_signals);
+ sigfillset (&all_signals);
+ ::posix_spawnattr_setsigmask(&attr, &all_signals);
+ ::posix_spawnattr_setsigdefault(&attr, &no_signals);
+
+ short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
+
+ error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX);
+ error.LogIfError(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags);
+ if (error.Fail())
+ return error;
+
+ const size_t num_file_actions = launch_info.GetNumFileActions ();
+ posix_spawn_file_actions_t file_actions, *file_action_ptr = NULL;
+ // Make a quick class that will cleanup the posix spawn attributes in case
+ // we return in the middle of this function.
+ lldb_utility::CleanUp <posix_spawn_file_actions_t *, int>
+ posix_spawn_file_actions_cleanup (file_action_ptr, NULL, posix_spawn_file_actions_destroy);
+
+ if (num_file_actions > 0)
+ {
+ error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
+ error.LogIfError(log, "::posix_spawn_file_actions_init ( &file_actions )");
+ if (error.Fail())
+ return error;
+
+ file_action_ptr = &file_actions;
+ posix_spawn_file_actions_cleanup.set(file_action_ptr);
+
+ for (size_t i = 0; i < num_file_actions; ++i)
+ {
+ const ProcessLaunchInfo::FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i);
+ if (launch_file_action &&
+ !ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions,
+ launch_file_action,
+ log,
+ error))
+ return error;
+ }
+ }
+
+ // Change working directory if neccessary.
+ char current_dir[PATH_MAX];
+ current_dir[0] = '\0';
+
+ const char *working_dir = launch_info.GetWorkingDirectory();
+ if (working_dir != NULL)
+ {
+ if (::getcwd(current_dir, sizeof(current_dir)) == NULL)
+ {
+ error.SetError(errno, eErrorTypePOSIX);
+ error.LogIfError(log, "unable to save the current directory");
+ return error;
+ }
+
+ if (::chdir(working_dir) == -1)
+ {
+ error.SetError(errno, eErrorTypePOSIX);
+ error.LogIfError(log, "unable to change working directory to %s", working_dir);
+ return error;
+ }
+ }
+
+ const char *tmp_argv[2];
+ char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector();
+ char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector();
+
+ // Prepare minimal argument list if we didn't get it from the launch_info structure.
+ // We must pass argv into posix_spawnp and it must contain at least two items -
+ // pointer to an executable and NULL.
+ if (argv == NULL)
+ {
+ tmp_argv[0] = exe_path;
+ tmp_argv[1] = NULL;
+ argv = (char * const*)tmp_argv;
+ }
+
+ error.SetError (::posix_spawnp (&pid,
+ exe_path,
+ (num_file_actions > 0) ? &file_actions : NULL,
+ &attr,
+ argv,
+ envp),
+ eErrorTypePOSIX);
+
+ error.LogIfError(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
+ pid, exe_path, file_action_ptr, &attr, argv, envp);
+
+ // Change back the current directory.
+ // NOTE: do not override previously established error from posix_spawnp.
+ if (working_dir != NULL && ::chdir(current_dir) == -1 && error.Success())
+ {
+ error.SetError(errno, eErrorTypePOSIX);
+ error.LogIfError(log, "unable to change current directory back to %s",
+ current_dir);
+ }
+
+ return error;
+}
+
+
+Error
+Host::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+ Error error;
+ char exe_path[PATH_MAX];
+
+ PlatformSP host_platform_sp (Platform::GetDefaultPlatform ());
+
+ const ArchSpec &arch_spec = launch_info.GetArchitecture();
+
+ FileSpec exe_spec(launch_info.GetExecutableFile());
+
+ FileSpec::FileType file_type = exe_spec.GetFileType();
+ if (file_type != FileSpec::eFileTypeRegular)
+ {
+ lldb::ModuleSP exe_module_sp;
+ error = host_platform_sp->ResolveExecutable (exe_spec,
+ arch_spec,
+ exe_module_sp,
+ NULL);
+
+ if (error.Fail())
+ return error;
+
+ if (exe_module_sp)
+ exe_spec = exe_module_sp->GetFileSpec();
+ }
+
+ if (exe_spec.Exists())
+ {
+ exe_spec.GetPath (exe_path, sizeof(exe_path));
+ }
+ else
+ {
+ launch_info.GetExecutableFile().GetPath (exe_path, sizeof(exe_path));
+ error.SetErrorStringWithFormat ("executable doesn't exist: '%s'", exe_path);
+ return error;
+ }
+
+ assert(!launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY));
+
+ ::pid_t pid = LLDB_INVALID_PROCESS_ID;
+
+ error = LaunchProcessPosixSpawn(exe_path, launch_info, pid);
+
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ {
+ // If all went well, then set the process ID into the launch info
+ launch_info.SetProcessID(pid);
+
+ // Make sure we reap any processes we spawn or we will have zombies.
+ if (!launch_info.MonitorProcess())
+ {
+ const bool monitor_signals = false;
+ StartMonitoringChildProcess (Process::SetProcessExitStatus,
+ NULL,
+ pid,
+ monitor_signals);
+ }
+ }
+ else
+ {
+ // Invalid process ID, something didn't go well
+ if (error.Success())
+ error.SetErrorString ("process launch failed for unknown reasons");
+ }
+ return error;
+}
+
+#endif // defined(__linux__) or defined(__FreeBSD__)
+
+#ifndef _WIN32
+
+size_t
+Host::GetPageSize()
+{
+ return ::getpagesize();
+}
uint32_t
Host::GetNumberCPUS ()
@@ -1500,14 +1762,7 @@ Host::GetNumberCPUS ()
#if defined(__APPLE__) or defined (__linux__) or defined (__FreeBSD__) or defined (__FreeBSD_kernel__)
g_num_cores = ::sysconf(_SC_NPROCESSORS_ONLN);
-
-#elif defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-
- // Header file for this might need to be included at the top of this file
- SYSTEM_INFO system_info;
- ::GetSystemInfo (&system_info);
- g_num_cores = system_info.dwNumberOfProcessors;
-
+
#else
// Assume POSIX support if a host specific case has not been supplied above
@@ -1540,7 +1795,13 @@ Host::GetNumberCPUS ()
return g_num_cores;
}
+void
+Host::Kill(lldb::pid_t pid, int signo)
+{
+ ::kill(pid, signo);
+}
+#endif
#if !defined (__APPLE__)
bool
@@ -1560,9 +1821,169 @@ Host::SetCrashDescription (const char *description)
}
lldb::pid_t
-LaunchApplication (const FileSpec &app_file_spec)
+Host::LaunchApplication (const FileSpec &app_file_spec)
{
return LLDB_INVALID_PROCESS_ID;
}
+uint32_t
+Host::MakeDirectory (const char* path, mode_t mode)
+{
+ return UINT32_MAX;
+}
+#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,
+ mode_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();
+ GetFDToFileMap()[fd] = file_sp;
+ return fd;
+}
+
+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/Mutex.cpp b/source/Host/common/Mutex.cpp
index 39cd8c6adb4e..4e0135535628 100644
--- a/source/Host/common/Mutex.cpp
+++ b/source/Host/common/Mutex.cpp
@@ -10,9 +10,11 @@
#include "lldb/Host/Mutex.h"
#include "lldb/Host/Host.h"
+#ifndef _WIN32
+#include <pthread.h>
+#endif
#include <string.h>
#include <stdio.h>
-#include <unistd.h>
#if 0
// This logging is way too verbose to enable even for a log channel.
@@ -177,6 +179,8 @@ Mutex::Locker::TryLock (Mutex &mutex, const char *failure_message)
return m_mutex_ptr != NULL;
}
+#ifndef _WIN32
+
//----------------------------------------------------------------------
// Default constructor.
//
@@ -253,15 +257,6 @@ Mutex::~Mutex()
}
//----------------------------------------------------------------------
-// Mutex get accessor.
-//----------------------------------------------------------------------
-pthread_mutex_t *
-Mutex::GetMutex()
-{
- return &m_mutex;
-}
-
-//----------------------------------------------------------------------
// Locks the mutex owned by this object, if the mutex is already
// locked, the calling thread will block until the mutex becomes
// available.
@@ -341,6 +336,17 @@ Mutex::Unlock()
return err;
}
+#endif
+
+//----------------------------------------------------------------------
+// Mutex get accessor.
+//----------------------------------------------------------------------
+lldb::mutex_t *
+Mutex::GetMutex()
+{
+ return &m_mutex;
+}
+
#ifdef LLDB_CONFIGURATION_DEBUG
int
TrackingMutex::Unlock ()
diff --git a/source/Host/common/OptionParser.cpp b/source/Host/common/OptionParser.cpp
new file mode 100644
index 000000000000..287292ee74af
--- /dev/null
+++ b/source/Host/common/OptionParser.cpp
@@ -0,0 +1,61 @@
+//===-- source/Host/common/OptionParser.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/OptionParser.h"
+
+#ifdef _MSC_VER
+#include "../windows/msvc/getopt.inc"
+#else
+#ifdef _WIN32
+#define _BSD_SOURCE // Required so that getopt.h defines optreset
+#endif
+#include <getopt.h>
+#endif
+
+using namespace lldb_private;
+
+void
+OptionParser::Prepare()
+{
+#ifdef __GLIBC__
+ optind = 0;
+#else
+ optreset = 1;
+ optind = 1;
+#endif
+}
+
+void
+OptionParser::EnableError(bool error)
+{
+ opterr = error ? 1 : 0;
+}
+
+int
+OptionParser::Parse(int argc, char * const argv [],
+ const char *optstring,
+ const Option *longopts, int *longindex)
+{
+ return getopt_long_only(argc, argv, optstring, (const option*)longopts, longindex);
+}
+
+char* OptionParser::GetOptionArgument()
+{
+ return optarg;
+}
+
+int OptionParser::GetOptionIndex()
+{
+ return optind;
+}
+
+int OptionParser::GetOptionErrorCause()
+{
+ return optopt;
+}
diff --git a/source/Host/common/ProcessRunLock.cpp b/source/Host/common/ProcessRunLock.cpp
new file mode 100644
index 000000000000..669a96ddd70c
--- /dev/null
+++ b/source/Host/common/ProcessRunLock.cpp
@@ -0,0 +1,71 @@
+#ifndef _WIN32
+
+#include "lldb/Host/ProcessRunLock.h"
+
+namespace lldb_private {
+
+ ProcessRunLock::ProcessRunLock()
+ : m_running(false)
+ {
+ int err = ::pthread_rwlock_init(&m_rwlock, NULL); (void) err;
+ //#if LLDB_CONFIGURATION_DEBUG
+ // assert(err == 0);
+ //#endif
+ }
+
+ ProcessRunLock::~ProcessRunLock()
+ {
+ int err = ::pthread_rwlock_destroy(&m_rwlock); (void) err;
+ //#if LLDB_CONFIGURATION_DEBUG
+ // assert(err == 0);
+ //#endif
+ }
+
+ bool ProcessRunLock::ReadTryLock()
+ {
+ ::pthread_rwlock_rdlock(&m_rwlock);
+ if (m_running == false)
+ {
+ return true;
+ }
+ ::pthread_rwlock_unlock(&m_rwlock);
+ return false;
+ }
+
+ bool ProcessRunLock::ReadUnlock()
+ {
+ return ::pthread_rwlock_unlock(&m_rwlock) == 0;
+ }
+
+ bool ProcessRunLock::SetRunning()
+ {
+ ::pthread_rwlock_wrlock(&m_rwlock);
+ m_running = true;
+ ::pthread_rwlock_unlock(&m_rwlock);
+ return true;
+ }
+
+ bool ProcessRunLock::TrySetRunning()
+ {
+ bool r;
+
+ if (::pthread_rwlock_trywrlock(&m_rwlock) == 0)
+ {
+ r = !m_running;
+ m_running = true;
+ ::pthread_rwlock_unlock(&m_rwlock);
+ return r;
+ }
+ return false;
+ }
+
+ bool ProcessRunLock::SetStopped()
+ {
+ ::pthread_rwlock_wrlock(&m_rwlock);
+ m_running = false;
+ ::pthread_rwlock_unlock(&m_rwlock);
+ return true;
+ }
+}
+
+#endif
diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp
index a22dc7a01c15..1fa7531af9dc 100644
--- a/source/Host/common/SocketAddress.cpp
+++ b/source/Host/common/SocketAddress.cpp
@@ -11,6 +11,9 @@
#include <stddef.h>
// C Includes
+#if !defined(_MSC_VER)
+#include <arpa/inet.h>
+#endif
#include <assert.h>
#include <string.h>
diff --git a/source/Host/common/Terminal.cpp b/source/Host/common/Terminal.cpp
index 89d21cf0bf6c..f63c468bb92c 100644
--- a/source/Host/common/Terminal.cpp
+++ b/source/Host/common/Terminal.cpp
@@ -8,10 +8,8 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/Terminal.h"
-#include "lldb/Host/Config.h"
#include <fcntl.h>
-#include <unistd.h>
#include <signal.h>
#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
@@ -24,6 +22,7 @@ using namespace lldb_private;
bool
Terminal::IsATerminal () const
{
+
return m_fd >= 0 && ::isatty (m_fd);
}
@@ -108,7 +107,9 @@ Terminal::SetCanonical (bool enabled)
TerminalState::TerminalState() :
m_tty(),
m_tflags(-1),
+#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
m_termios_ap(),
+#endif
m_process_group(-1)
{
}
@@ -125,7 +126,9 @@ TerminalState::Clear ()
{
m_tty.Clear();
m_tflags = -1;
+#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
m_termios_ap.reset();
+#endif
m_process_group = -1;
}
@@ -140,7 +143,9 @@ TerminalState::Save (int fd, bool save_process_group)
m_tty.SetFileDescriptor(fd);
if (m_tty.IsATerminal())
{
+#ifndef LLDB_DISABLE_POSIX
m_tflags = ::fcntl (fd, F_GETFL, 0);
+#endif
#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
if (m_termios_ap.get() == NULL)
m_termios_ap.reset (new struct termios);
@@ -148,16 +153,20 @@ TerminalState::Save (int fd, bool save_process_group)
if (err != 0)
m_termios_ap.reset();
#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#ifndef LLDB_DISABLE_POSIX
if (save_process_group)
m_process_group = ::tcgetpgrp (0);
else
m_process_group = -1;
+#endif
}
else
{
m_tty.Clear();
m_tflags = -1;
+#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
m_termios_ap.reset();
+#endif
m_process_group = -1;
}
return IsValid();
@@ -173,14 +182,17 @@ TerminalState::Restore () const
if (IsValid())
{
const int fd = m_tty.GetFileDescriptor();
+#ifndef LLDB_DISABLE_POSIX
if (TFlagsIsValid())
fcntl (fd, F_SETFL, m_tflags);
+#endif
#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
if (TTYStateIsValid())
tcsetattr (fd, TCSANOW, m_termios_ap.get());
#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
+#ifndef LLDB_DISABLE_POSIX
if (ProcessGroupIsValid())
{
// Save the original signal handler.
@@ -191,6 +203,7 @@ TerminalState::Restore () const
// Restore the original signal handler.
signal (SIGTTOU, saved_sigttou_callback);
}
+#endif
return true;
}
return false;
@@ -224,7 +237,11 @@ TerminalState::TFlagsIsValid() const
bool
TerminalState::TTYStateIsValid() const
{
+#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED
return m_termios_ap.get() != 0;
+#else
+ return false;
+#endif
}
//----------------------------------------------------------------------
diff --git a/source/Host/common/TimeValue.cpp b/source/Host/common/TimeValue.cpp
index 303ac94058b0..b471a3dd1f15 100644
--- a/source/Host/common/TimeValue.cpp
+++ b/source/Host/common/TimeValue.cpp
@@ -8,11 +8,17 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/TimeValue.h"
+#include "lldb/Host/Config.h"
// C Includes
#include <stddef.h>
#include <time.h>
#include <cstring>
+
+#ifdef _MSC_VER
+#include "lldb/Host/windows/windows.h"
+#endif
+
// C++ Includes
// Other libraries and framework includes
// Project includes
@@ -42,8 +48,8 @@ TimeValue::TimeValue(const struct timespec& ts) :
{
}
-TimeValue::TimeValue(const struct timeval& tv) :
- m_nano_seconds ((uint64_t) tv.tv_sec * NanoSecPerSec + (uint64_t) tv.tv_usec * NanoSecPerMicroSec)
+TimeValue::TimeValue(uint32_t seconds, uint32_t nanos) :
+ m_nano_seconds((uint64_t) seconds * NanoSecPerSec + nanos)
{
}
@@ -84,15 +90,6 @@ TimeValue::GetAsTimeSpec () const
return ts;
}
-struct timeval
-TimeValue::GetAsTimeVal () const
-{
- struct timeval tv;
- tv.tv_sec = m_nano_seconds / NanoSecPerSec;
- tv.tv_usec = (m_nano_seconds % NanoSecPerSec) / NanoSecPerMicroSec;
- return tv;
-}
-
void
TimeValue::Clear ()
{
@@ -126,9 +123,22 @@ TimeValue::OffsetWithNanoSeconds (uint64_t nsec)
TimeValue
TimeValue::Now()
{
+ uint32_t seconds, nanoseconds;
+#if _MSC_VER
+ SYSTEMTIME st;
+ GetSystemTime(&st);
+ nanoseconds = st.wMilliseconds * 1000000;
+ FILETIME ft;
+ SystemTimeToFileTime(&st, &ft);
+
+ seconds = ((((uint64_t)ft.dwHighDateTime) << 32 | ft.dwLowDateTime) / 10000000) - 11644473600ULL;
+#else
struct timeval tv;
gettimeofday(&tv, NULL);
- TimeValue now(tv);
+ seconds = tv.tv_sec;
+ nanoseconds = tv.tv_usec * NanoSecPerMicroSec;
+#endif
+ TimeValue now(seconds, nanoseconds);
return now;
}
@@ -148,6 +158,7 @@ TimeValue::Dump (Stream *s, uint32_t width) const
if (s == NULL)
return;
+#ifndef LLDB_DISABLE_POSIX
char time_buf[32];
time_t time = GetAsSecondsSinceJan1_1970();
char *time_cstr = ::ctime_r(&time, time_buf);
@@ -163,6 +174,7 @@ TimeValue::Dump (Stream *s, uint32_t width) const
}
else if (width > 0)
s->Printf("%-*s", width, "");
+#endif
}
bool
diff --git a/source/Host/freebsd/Host.cpp b/source/Host/freebsd/Host.cpp
index 405e7eacf5a9..c4a6ca37e9c4 100644
--- a/source/Host/freebsd/Host.cpp
+++ b/source/Host/freebsd/Host.cpp
@@ -15,25 +15,30 @@
#include <sys/user.h>
#include <sys/utsname.h>
#include <sys/sysctl.h>
+#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/exec.h>
#include <machine/elf.h>
-
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Error.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/Host.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Log.h"
#include "lldb/Target/Process.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
+#include "lldb/Utility/CleanUp.h"
+
#include "llvm/Support/Host.h"
@@ -44,7 +49,6 @@ extern "C" {
using namespace lldb;
using namespace lldb_private;
-
class FreeBSDThread
{
public:
@@ -120,7 +124,8 @@ Host::GetEnvironment (StringList &env)
{
char *v;
char **var = environ;
- for (; var != NULL && *var != NULL; ++var) {
+ for (; var != NULL && *var != NULL; ++var)
+ {
v = strchr(*var, (int)'-');
if (v == NULL)
continue;
@@ -135,34 +140,30 @@ Host::GetOSVersion(uint32_t &major,
uint32_t &update)
{
struct utsname un;
- int status;
+ ::memset(&un, 0, sizeof(utsname));
if (uname(&un) < 0)
return false;
- status = sscanf(un.release, "%u.%u", &major, &minor);
+ int status = sscanf(un.release, "%u.%u", &major, &minor);
return status == 2;
}
-Error
-Host::LaunchProcess (ProcessLaunchInfo &launch_info)
-{
- Error error;
- assert(!"Not implemented yet!!!");
- return error;
-}
-
bool
Host::GetOSBuildString (std::string &s)
{
int mib[2] = { CTL_KERN, KERN_OSREV };
- char cstr[PATH_MAX];
- size_t cstr_len = sizeof(cstr);
- if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0)
+ char osrev_str[12];
+ uint32_t osrev = 0;
+ size_t osrev_len = sizeof(osrev);
+
+ if (::sysctl (mib, 2, &osrev, &osrev_len, NULL, 0) == 0)
{
- s.assign (cstr, cstr_len);
+ ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev);
+ s.assign (osrev_str);
return true;
}
+
s.clear();
return false;
}
@@ -170,23 +171,25 @@ Host::GetOSBuildString (std::string &s)
bool
Host::GetOSKernelDescription (std::string &s)
{
- int mib[2] = { CTL_KERN, KERN_VERSION };
- char cstr[PATH_MAX];
- size_t cstr_len = sizeof(cstr);
- if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0)
- {
- s.assign (cstr, cstr_len);
- return true;
- }
+ 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)
{
- if (process_info.ProcessIDIsValid()) {
+ if (process_info.ProcessIDIsValid())
+ {
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() };
char arg_data[8192];
@@ -235,7 +238,8 @@ GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr,
static bool
GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info)
{
- if (process_info.ProcessIDIsValid()) {
+ if (process_info.ProcessIDIsValid())
+ {
process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
return true;
}
@@ -279,16 +283,95 @@ GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info)
return false;
}
+uint32_t
+Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
+{
+ std::vector<struct kinfo_proc> kinfos;
+
+ int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
+
+ size_t pid_data_size = 0;
+ if (::sysctl (mib, 3, NULL, &pid_data_size, NULL, 0) != 0)
+ return 0;
+
+ // Add a few extra in case a few more show up
+ const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10;
+
+ kinfos.resize (estimated_pid_count);
+ pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);
+
+ if (::sysctl (mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0)
+ return 0;
+
+ 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 uid_t our_uid = getuid();
+ for (int i = 0; i < actual_pid_count; i++)
+ {
+ const struct kinfo_proc &kinfo = kinfos[i];
+ const bool kinfo_user_matches = (all_users ||
+ (kinfo.ki_ruid == our_uid) ||
+ // Special case, if lldb is being run as root we can attach to anything.
+ (our_uid == 0)
+ );
+
+ if (kinfo_user_matches == false || // Make sure the user is acceptable
+ kinfo.ki_pid == our_pid || // Skip this process
+ kinfo.ki_pid == 0 || // Skip kernel (kernel pid is zero)
+ kinfo.ki_stat == SZOMB || // Zombies are bad, they like brains...
+ kinfo.ki_flag & P_TRACED || // Being debugged?
+ kinfo.ki_flag & P_WEXIT) // Working on exiting
+ continue;
+
+ // Every thread is a process in FreeBSD, but all the threads of a single process
+ // have the same pid. Do not store the process info in the result list if a process
+ // with given identifier is already registered there.
+ bool already_registered = false;
+ for (uint32_t pi = 0;
+ !already_registered &&
+ (const int)kinfo.ki_numthreads > 1 &&
+ pi < (const uint32_t)process_infos.GetSize(); pi++)
+ already_registered = (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid);
+
+ if (already_registered)
+ continue;
+
+ ProcessInstanceInfo process_info;
+ process_info.SetProcessID (kinfo.ki_pid);
+ process_info.SetParentProcessID (kinfo.ki_ppid);
+ process_info.SetUserID (kinfo.ki_ruid);
+ process_info.SetGroupID (kinfo.ki_rgid);
+ process_info.SetEffectiveUserID (kinfo.ki_svuid);
+ process_info.SetEffectiveGroupID (kinfo.ki_svgid);
+
+ // Make sure our info matches before we go fetch the name and cpu type
+ if (match_info.Matches (process_info) &&
+ GetFreeBSDProcessArgs (&match_info, process_info))
+ {
+ GetFreeBSDProcessCPUType (process_info);
+ if (match_info.Matches (process_info))
+ process_infos.Append (process_info);
+ }
+ }
+
+ return process_infos.GetSize();
+}
+
bool
Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
process_info.SetProcessID(pid);
- if (GetFreeBSDProcessArgs(NULL, process_info)) {
+
+ if (GetFreeBSDProcessArgs(NULL, process_info))
+ {
// should use libprocstat instead of going right into sysctl?
GetFreeBSDProcessCPUType(process_info);
GetFreeBSDProcessUserAndGroup(process_info);
return true;
}
+
process_info.Clear();
return false;
}
diff --git a/source/Interpreter/Args.cpp b/source/Interpreter/Args.cpp
index e6d20435803f..ff94e0f60212 100644
--- a/source/Interpreter/Args.cpp
+++ b/source/Interpreter/Args.cpp
@@ -10,7 +10,6 @@
#include "lldb/lldb-python.h"
// C Includes
-#include <getopt.h>
#include <cstdlib>
// C++ Includes
// Other libraries and framework includes
@@ -621,7 +620,7 @@ Args::ParseOptions (Options &options)
{
StreamString sstr;
Error error;
- struct option *long_options = options.GetLongOptions();
+ Option *long_options = options.GetLongOptions();
if (long_options == NULL)
{
error.SetErrorStringWithFormat("invalid long options");
@@ -638,24 +637,19 @@ Args::ParseOptions (Options &options)
switch (long_options[i].has_arg)
{
default:
- case no_argument: break;
- case required_argument: sstr << ':'; break;
- case optional_argument: sstr << "::"; break;
+ case OptionParser::eNoArgument: break;
+ case OptionParser::eRequiredArgument: sstr << ':'; break;
+ case OptionParser::eOptionalArgument: sstr << "::"; break;
}
}
}
}
-#ifdef __GLIBC__
- optind = 0;
-#else
- optreset = 1;
- optind = 1;
-#endif
+ OptionParser::Prepare();
int val;
while (1)
{
int long_options_index = -1;
- val = ::getopt_long_only(GetArgumentCount(),
+ val = OptionParser::Parse(GetArgumentCount(),
GetArgumentVector(),
sstr.GetData(),
long_options,
@@ -693,7 +687,7 @@ Args::ParseOptions (Options &options)
if (long_options_index >= 0)
{
error = options.SetOptionValue(long_options_index,
- long_options[long_options_index].has_arg == no_argument ? NULL : optarg);
+ long_options[long_options_index].has_arg == OptionParser::eNoArgument ? NULL : OptionParser::GetOptionArgument());
}
else
{
@@ -704,7 +698,7 @@ Args::ParseOptions (Options &options)
}
// Update our ARGV now that get options has consumed all the options
- m_argv.erase(m_argv.begin(), m_argv.begin() + optind);
+ m_argv.erase(m_argv.begin(), m_argv.begin() + OptionParser::GetOptionIndex());
UpdateArgsAfterOptionParsing ();
return error;
}
@@ -1223,7 +1217,7 @@ Args::LongestCommonPrefix (std::string &common_prefix)
}
size_t
-Args::FindArgumentIndexForOption (struct option *long_options, int long_options_index)
+Args::FindArgumentIndexForOption (Option *long_options, int long_options_index)
{
char short_buffer[3];
char long_buffer[255];
@@ -1275,7 +1269,7 @@ Args::ParseAliasOptions (Options &options,
{
StreamString sstr;
int i;
- struct option *long_options = options.GetLongOptions();
+ Option *long_options = options.GetLongOptions();
if (long_options == NULL)
{
@@ -1292,29 +1286,24 @@ Args::ParseAliasOptions (Options &options,
switch (long_options[i].has_arg)
{
default:
- case no_argument:
+ case OptionParser::eNoArgument:
break;
- case required_argument:
+ case OptionParser::eRequiredArgument:
sstr << ":";
break;
- case optional_argument:
+ case OptionParser::eOptionalArgument:
sstr << "::";
break;
}
}
}
-#ifdef __GLIBC__
- optind = 0;
-#else
- optreset = 1;
- optind = 1;
-#endif
+ OptionParser::Prepare();
int val;
while (1)
{
int long_options_index = -1;
- val = ::getopt_long_only (GetArgumentCount(),
+ val = OptionParser::Parse (GetArgumentCount(),
GetArgumentVector(),
sstr.GetData(),
long_options,
@@ -1358,17 +1347,17 @@ Args::ParseAliasOptions (Options &options,
switch (long_options[long_options_index].has_arg)
{
- case no_argument:
+ case OptionParser::eNoArgument:
option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
- OptionArgValue (no_argument, "<no-argument>")));
+ OptionArgValue (OptionParser::eNoArgument, "<no-argument>")));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
break;
- case required_argument:
- if (optarg != NULL)
+ case OptionParser::eRequiredArgument:
+ if (OptionParser::GetOptionArgument() != NULL)
{
option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
- OptionArgValue (required_argument,
- std::string (optarg))));
+ OptionArgValue (OptionParser::eRequiredArgument,
+ std::string (OptionParser::GetOptionArgument()))));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
@@ -1378,18 +1367,18 @@ Args::ParseAliasOptions (Options &options,
result.SetStatus (eReturnStatusFailed);
}
break;
- case optional_argument:
- if (optarg != NULL)
+ case OptionParser::eOptionalArgument:
+ if (OptionParser::GetOptionArgument() != NULL)
{
option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
- OptionArgValue (optional_argument,
- std::string (optarg))));
+ OptionArgValue (OptionParser::eOptionalArgument,
+ std::string (OptionParser::GetOptionArgument()))));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
{
option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
- OptionArgValue (optional_argument, "<no-argument>")));
+ OptionArgValue (OptionParser::eOptionalArgument, "<no-argument>")));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
break;
@@ -1421,10 +1410,10 @@ Args::ParseAliasOptions (Options &options,
raw_input_string.erase (pos, strlen (tmp_arg));
}
ReplaceArgumentAtIndex (idx, "");
- if ((long_options[long_options_index].has_arg != no_argument)
- && (optarg != NULL)
+ if ((long_options[long_options_index].has_arg != OptionParser::eNoArgument)
+ && (OptionParser::GetOptionArgument() != NULL)
&& (idx+1 < GetArgumentCount())
- && (strcmp (optarg, GetArgumentAtIndex(idx+1)) == 0))
+ && (strcmp (OptionParser::GetOptionArgument(), GetArgumentAtIndex(idx+1)) == 0))
{
if (raw_input_string.size() > 0)
{
@@ -1452,7 +1441,7 @@ Args::ParseArgsForCompletion
)
{
StreamString sstr;
- struct option *long_options = options.GetLongOptions();
+ Option *long_options = options.GetLongOptions();
option_element_vector.clear();
if (long_options == NULL)
@@ -1472,31 +1461,26 @@ Args::ParseArgsForCompletion
switch (long_options[i].has_arg)
{
default:
- case no_argument:
+ case OptionParser::eNoArgument:
break;
- case required_argument:
+ case OptionParser::eRequiredArgument:
sstr << ":";
break;
- case optional_argument:
+ case OptionParser::eOptionalArgument:
sstr << "::";
break;
}
}
}
-#ifdef __GLIBC__
- optind = 0;
-#else
- optreset = 1;
- optind = 1;
-#endif
- opterr = 0;
+ OptionParser::Prepare();
+ OptionParser::EnableError(false);
int val;
const OptionDefinition *opt_defs = options.GetDefinitions();
- // Fooey... getopt_long_only permutes the GetArgumentVector to move the options to the front.
- // So we have to build another Arg and pass that to getopt_long_only so it doesn't
+ // Fooey... OptionParser::Parse permutes the GetArgumentVector to move the options to the front.
+ // So we have to build another Arg and pass that to OptionParser::Parse so it doesn't
// change the one we have.
std::vector<const char *> dummy_vec (GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
@@ -1509,7 +1493,7 @@ Args::ParseArgsForCompletion
bool missing_argument = false;
int long_options_index = -1;
- val = ::getopt_long_only (dummy_vec.size() - 1,
+ val = OptionParser::Parse (dummy_vec.size() - 1,
(char *const *) &dummy_vec.front(),
sstr.GetData(),
long_options,
@@ -1527,18 +1511,18 @@ Args::ParseArgsForCompletion
// Handling the "--" is a little tricky, since that may mean end of options or arguments, or the
// user might want to complete options by long name. I make this work by checking whether the
// cursor is in the "--" argument, and if so I assume we're completing the long option, otherwise
- // I let it pass to getopt_long_only which will terminate the option parsing.
+ // I let it pass to OptionParser::Parse which will terminate the option parsing.
// Note, in either case we continue parsing the line so we can figure out what other options
// were passed. This will be useful when we come to restricting completions based on what other
// options we've seen on the line.
- if (optind < dummy_vec.size() - 1
- && (strcmp (dummy_vec[optind-1], "--") == 0))
+ if (OptionParser::GetOptionIndex() < dummy_vec.size() - 1
+ && (strcmp (dummy_vec[OptionParser::GetOptionIndex()-1], "--") == 0))
{
- dash_dash_pos = optind - 1;
- if (optind - 1 == cursor_index)
+ dash_dash_pos = OptionParser::GetOptionIndex() - 1;
+ if (OptionParser::GetOptionIndex() - 1 == cursor_index)
{
- option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, optind - 1,
+ option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, OptionParser::GetOptionIndex() - 1,
OptionArgElement::eBareDoubleDash));
continue;
}
@@ -1550,7 +1534,7 @@ Args::ParseArgsForCompletion
}
else if (val == '?')
{
- option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
+ option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
OptionArgElement::eUnrecognizedArg));
continue;
}
@@ -1561,7 +1545,7 @@ Args::ParseArgsForCompletion
else if (val == ':')
{
// This is a missing argument.
- val = optopt;
+ val = OptionParser::GetOptionErrorCause();
missing_argument = true;
}
@@ -1599,51 +1583,51 @@ Args::ParseArgsForCompletion
switch (long_options[long_options_index].has_arg)
{
- case no_argument:
- option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 1, 0));
+ case OptionParser::eNoArgument:
+ option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));
break;
- case required_argument:
- if (optarg != NULL)
+ case OptionParser::eRequiredArgument:
+ if (OptionParser::GetOptionArgument() != NULL)
{
int arg_index;
if (missing_argument)
arg_index = -1;
else
- arg_index = optind - 1;
+ arg_index = OptionParser::GetOptionIndex() - 1;
- option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, arg_index));
+ option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, arg_index));
}
else
{
- option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 1, -1));
+ option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, -1));
}
break;
- case optional_argument:
- if (optarg != NULL)
+ case OptionParser::eOptionalArgument:
+ if (OptionParser::GetOptionArgument() != NULL)
{
- option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, optind - 1));
+ option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1));
}
else
{
- option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, optind - 1));
+ option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1));
}
break;
default:
// The options table is messed up. Here we'll just continue
- option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
+ option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
OptionArgElement::eUnrecognizedArg));
break;
}
}
else
{
- option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
+ option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
OptionArgElement::eUnrecognizedArg));
}
}
// 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 getopt_long_only just ignores
+ // 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.
if ((dash_dash_pos == -1 || cursor_index < dash_dash_pos)
diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp
index db2f2fafbef1..794cc716bda5 100644
--- a/source/Interpreter/CommandInterpreter.cpp
+++ b/source/Interpreter/CommandInterpreter.cpp
@@ -11,8 +11,6 @@
#include <string>
#include <vector>
-
-#include <getopt.h>
#include <stdlib.h>
#include "CommandObjectScript.h"
@@ -230,6 +228,13 @@ CommandInterpreter::Initialize ()
AddAlias ("t", cmd_obj_sp);
}
+ cmd_obj_sp = GetCommandSPExact ("_regexp-jump",false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("j", cmd_obj_sp);
+ AddAlias ("jump", cmd_obj_sp);
+ }
+
cmd_obj_sp = GetCommandSPExact ("_regexp-list", false);
if (cmd_obj_sp)
{
@@ -318,7 +323,7 @@ CommandInterpreter::Initialize ()
#if defined (__arm__)
ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
#else
- ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=/bin/bash --", alias_arguments_vector_sp);
+ ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=" LLDB_DEFAULT_SHELL " --", alias_arguments_vector_sp);
#endif
AddAlias ("r", cmd_obj_sp);
AddAlias ("run", cmd_obj_sp);
@@ -587,7 +592,7 @@ CommandInterpreter::LoadCommandDictionary ()
list_regex_cmd_ap(new CommandObjectRegexCommand (*this,
"_regexp-list",
"Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.",
- "_regexp-list [<line>]\n_regexp-attach [<file>:<line>]\n_regexp-attach [<file>:<line>]",
+ "_regexp-list [<line>]\n_regexp-list [<file>:<line>]\n_regexp-list [<file>:<line>]",
2,
CommandCompletions::eSourceFileCompletion));
if (list_regex_cmd_ap.get())
@@ -620,6 +625,26 @@ CommandInterpreter::LoadCommandDictionary ()
}
}
+ std::unique_ptr<CommandObjectRegexCommand>
+ jump_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-jump",
+ "Sets the program counter to a new address.",
+ "_regexp-jump [<line>]\n"
+ "_regexp-jump [<+-lineoffset>]\n"
+ "_regexp-jump [<file>:<line>]\n"
+ "_regexp-jump [*<addr>]\n", 2));
+ if (jump_regex_cmd_ap.get())
+ {
+ if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") &&
+ jump_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "thread jump --line %1") &&
+ jump_regex_cmd_ap->AddRegexCommand("^([^:]+):([0-9]+)$", "thread jump --file %1 --line %2") &&
+ jump_regex_cmd_ap->AddRegexCommand("^([+\\-][0-9]+)$", "thread jump --by %1"))
+ {
+ CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_ap.release());
+ m_command_dict[jump_regex_cmd_sp->GetCommandName ()] = jump_regex_cmd_sp;
+ }
+ }
+
}
int
@@ -1326,9 +1351,9 @@ CommandInterpreter::BuildAliasResult (const char *alias_name,
else
{
result_str.Printf (" %s", option.c_str());
- if (value_type != optional_argument)
+ if (value_type != OptionParser::eOptionalArgument)
result_str.Printf (" ");
- if (value.compare ("<no_argument>") != 0)
+ if (value.compare ("<OptionParser::eNoArgument>") != 0)
{
int index = GetOptionArgumentPosition (value.c_str());
if (index == 0)
@@ -2295,7 +2320,7 @@ CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
}
else
{
- if (value_type != optional_argument)
+ if (value_type != OptionParser::eOptionalArgument)
new_args.AppendArgument (option.c_str());
if (value.compare ("<no-argument>") != 0)
{
@@ -2303,7 +2328,7 @@ CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
if (index == 0)
{
// value was NOT a positional argument; must be a real value
- if (value_type != optional_argument)
+ if (value_type != OptionParser::eOptionalArgument)
new_args.AppendArgument (value.c_str());
else
{
@@ -2330,7 +2355,7 @@ CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
}
- if (value_type != optional_argument)
+ if (value_type != OptionParser::eOptionalArgument)
new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
else
{
diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp
index 291dc4013573..c71ca28b0330 100644
--- a/source/Interpreter/CommandObject.cpp
+++ b/source/Interpreter/CommandObject.cpp
@@ -14,7 +14,6 @@
#include <string>
#include <map>
-#include <getopt.h>
#include <stdlib.h>
#include <ctype.h>
@@ -1099,6 +1098,7 @@ CommandObject::g_arguments_data[] =
{ 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 },
@@ -1123,6 +1123,9 @@ CommandObject::g_arguments_data[] =
{ 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." },
diff --git a/source/Interpreter/OptionGroupArchitecture.cpp b/source/Interpreter/OptionGroupArchitecture.cpp
index af103bb0bd9d..d8f35675fbab 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', required_argument, NULL, 0, eArgTypeArchitecture , "Specify the architecture for the target."},
+ { LLDB_OPT_SET_1 , false, "arch" , 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeArchitecture , "Specify the architecture for the target."},
};
uint32_t
diff --git a/source/Interpreter/OptionGroupBoolean.cpp b/source/Interpreter/OptionGroupBoolean.cpp
index 5b5b38478b02..feb135315e1b 100644
--- a/source/Interpreter/OptionGroupBoolean.cpp
+++ b/source/Interpreter/OptionGroupBoolean.cpp
@@ -30,7 +30,7 @@ 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.option_has_arg = no_argument_toggle_default ? no_argument : required_argument;
+ m_option_definition.option_has_arg = no_argument_toggle_default ? OptionParser::eNoArgument : OptionParser::eRequiredArgument;
m_option_definition.enum_values = NULL;
m_option_definition.completion_type = 0;
m_option_definition.argument_type = eArgTypeBoolean;
@@ -47,7 +47,7 @@ OptionGroupBoolean::SetOptionValue (CommandInterpreter &interpreter,
const char *option_arg)
{
Error error;
- if (m_option_definition.option_has_arg == no_argument)
+ if (m_option_definition.option_has_arg == OptionParser::eNoArgument)
{
// Not argument, toggle the default value and mark the option as having been set
m_value.SetCurrentValue (!m_value.GetDefaultValue());
diff --git a/source/Interpreter/OptionGroupFile.cpp b/source/Interpreter/OptionGroupFile.cpp
index 6867395789c7..48469a80417e 100644
--- a/source/Interpreter/OptionGroupFile.cpp
+++ b/source/Interpreter/OptionGroupFile.cpp
@@ -30,7 +30,7 @@ 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.option_has_arg = required_argument;
+ m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
m_option_definition.enum_values = NULL;
m_option_definition.completion_type = completion_type;
m_option_definition.argument_type = argument_type;
@@ -70,7 +70,7 @@ 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.option_has_arg = required_argument;
+ m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
m_option_definition.enum_values = NULL;
m_option_definition.completion_type = completion_type;
m_option_definition.argument_type = argument_type;
diff --git a/source/Interpreter/OptionGroupFormat.cpp b/source/Interpreter/OptionGroupFormat.cpp
index 790cbb668fa1..5cae3788f3bf 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', required_argument, NULL, 0, eArgTypeFormat , "Specify a format to be used for display."},
-{ LLDB_OPT_SET_2, false, "gdb-format",'G', required_argument, NULL, 0, eArgTypeGDBFormat, "Specify a format using a GDB format specifier string."},
-{ LLDB_OPT_SET_3, false, "size" ,'s', required_argument, NULL, 0, eArgTypeByteSize , "The size in bytes to use when displaying with the selected format."},
-{ LLDB_OPT_SET_4, false, "count" ,'c', required_argument, NULL, 0, eArgTypeCount , "The number of total items to display."},
+{ 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."},
};
uint32_t
@@ -158,7 +158,9 @@ OptionGroupFormat::SetOptionValue (CommandInterpreter &interpreter,
else
{
// Byte size is disabled, make sure it wasn't specified
- if (byte_size > 0)
+ // but if this is an address, it's actually necessary to
+ // specify one so don't error out
+ if (byte_size > 0 && format != lldb::eFormatAddressInfo)
{
error.SetErrorString ("this command doesn't support specifying a byte size");
return error;
diff --git a/source/Interpreter/OptionGroupOutputFile.cpp b/source/Interpreter/OptionGroupOutputFile.cpp
index aa01bf54964f..3bb8ab3b29cb 100644
--- a/source/Interpreter/OptionGroupOutputFile.cpp
+++ b/source/Interpreter/OptionGroupOutputFile.cpp
@@ -31,8 +31,8 @@ OptionGroupOutputFile::~OptionGroupOutputFile ()
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1 , false, "outfile", 'o', required_argument, NULL, 0, eArgTypeFilename , "Specify a path for capturing command output."},
- { LLDB_OPT_SET_1 , false, "append-outfile" , 'apnd', no_argument, NULL, 0, eArgTypeNone , "Append to the the file specified with '--outfile <path>'."},
+ { 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>'."},
};
uint32_t
diff --git a/source/Interpreter/OptionGroupPlatform.cpp b/source/Interpreter/OptionGroupPlatform.cpp
index a54edafd0196..83e28bdd02c1 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', required_argument, 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', required_argument, NULL, 0, eArgTypeNone, "Specify the initial SDK version to use prior to connecting." },
- { LLDB_OPT_SET_ALL, false, "build" , 'b', required_argument, NULL, 0, eArgTypeNone, "Specify the initial SDK build number." },
- { LLDB_OPT_SET_ALL, false, "sysroot" , 'S', required_argument, 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, 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." }
};
const OptionDefinition*
diff --git a/source/Interpreter/OptionGroupString.cpp b/source/Interpreter/OptionGroupString.cpp
index ee9623967c60..37a70d0bb242 100644
--- a/source/Interpreter/OptionGroupString.cpp
+++ b/source/Interpreter/OptionGroupString.cpp
@@ -31,7 +31,7 @@ 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.option_has_arg = required_argument;
+ m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
m_option_definition.enum_values = NULL;
m_option_definition.completion_type = completion_type;
m_option_definition.argument_type = argument_type;
diff --git a/source/Interpreter/OptionGroupUInt64.cpp b/source/Interpreter/OptionGroupUInt64.cpp
index e6996f702558..b66c84579232 100644
--- a/source/Interpreter/OptionGroupUInt64.cpp
+++ b/source/Interpreter/OptionGroupUInt64.cpp
@@ -31,7 +31,7 @@ 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.option_has_arg = required_argument;
+ m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
m_option_definition.enum_values = NULL;
m_option_definition.completion_type = completion_type;
m_option_definition.argument_type = argument_type;
diff --git a/source/Interpreter/OptionGroupUUID.cpp b/source/Interpreter/OptionGroupUUID.cpp
index 14bdc8494e45..fb3ebcf7745c 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', required_argument, NULL, 0, eArgTypeNone, "A module UUID value."},
+ { LLDB_OPT_SET_1 , false, "uuid", 'u', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone, "A module UUID value."},
};
uint32_t
diff --git a/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/source/Interpreter/OptionGroupValueObjectDisplay.cpp
index 22a7f37740d5..c79f49dc1d94 100644
--- a/source/Interpreter/OptionGroupValueObjectDisplay.cpp
+++ b/source/Interpreter/OptionGroupValueObjectDisplay.cpp
@@ -15,6 +15,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Target/Target.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Utility/Utils.h"
@@ -33,17 +34,17 @@ OptionGroupValueObjectDisplay::~OptionGroupValueObjectDisplay ()
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "dynamic-type", 'd', required_argument, 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', required_argument, NULL, 0, eArgTypeBoolean, "Show the object obeying its synthetic provider, if available."},
- { LLDB_OPT_SET_1, false, "depth", 'D', required_argument, NULL, 0, eArgTypeCount, "Set the max recurse depth when dumping aggregate types (default is infinity)."},
- { LLDB_OPT_SET_1, false, "flat", 'F', no_argument, 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', no_argument, NULL, 0, eArgTypeNone, "Show variable location information."},
- { LLDB_OPT_SET_1, false, "object-description", 'O', no_argument, NULL, 0, eArgTypeNone, "Print as an Objective-C object."},
- { LLDB_OPT_SET_1, false, "ptr-depth", 'P', required_argument, NULL, 0, eArgTypeCount, "The number of pointers to be traversed when dumping values (default is zero)."},
- { LLDB_OPT_SET_1, false, "show-types", 'T', no_argument, NULL, 0, eArgTypeNone, "Show variable types when dumping values."},
- { LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', optional_argument, NULL, 0, eArgTypeCount, "Set the depth at which omitting summary information stops (default is 1)."},
- { LLDB_OPT_SET_1, false, "raw-output", 'R', no_argument, NULL, 0, eArgTypeNone, "Don't use formatting options."},
- { LLDB_OPT_SET_1, false, "show-all-children", 'A', no_argument, NULL, 0, eArgTypeNone, "Ignore the upper bound on the number of children to show."},
+ { 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 }
};
@@ -147,12 +148,12 @@ OptionGroupValueObjectDisplay::OptionParsingStarting (CommandInterpreter &interp
}
}
-ValueObject::DumpValueObjectOptions
-OptionGroupValueObjectDisplay::GetAsDumpOptions (bool objc_is_compact,
+DumpValueObjectOptions
+OptionGroupValueObjectDisplay::GetAsDumpOptions (LanguageRuntimeDescriptionDisplayVerbosity lang_descr_verbosity,
lldb::Format format,
lldb::TypeSummaryImplSP summary_sp)
{
- ValueObject::DumpValueObjectOptions options;
+ DumpValueObjectOptions options;
options.SetMaximumPointerDepth(ptr_depth);
if (use_objc)
options.SetShowSummary(false);
@@ -169,7 +170,7 @@ OptionGroupValueObjectDisplay::GetAsDumpOptions (bool objc_is_compact,
.SetFormat(format)
.SetSummary(summary_sp);
- if (objc_is_compact)
+ if (lang_descr_verbosity == eLanguageRuntimeDescriptionDisplayVerbosityCompact)
options.SetHideRootType(use_objc)
.SetHideName(use_objc)
.SetHideValue(use_objc);
diff --git a/source/Interpreter/OptionGroupVariable.cpp b/source/Interpreter/OptionGroupVariable.cpp
index 316747eff036..31c2547e2c37 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', no_argument, NULL, 0, eArgTypeNone, "Omit function arguments."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-locals", 'l', no_argument, NULL, 0, eArgTypeNone, "Omit local variables."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-globals", 'g', no_argument, 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', no_argument, 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', no_argument, NULL, 0, eArgTypeRegularExpression, "The <variable-name> argument for name lookups are regular expressions."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "scope", 's', no_argument, NULL, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."},
- { LLDB_OPT_SET_1, false, "summary", 'y', required_argument, NULL, 0, eArgTypeName, "Specify the summary that the variable output should use."},
- { LLDB_OPT_SET_2, false, "summary-string", 'z', required_argument, 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, 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."},
};
static Error
diff --git a/source/Interpreter/OptionGroupWatchpoint.cpp b/source/Interpreter/OptionGroupWatchpoint.cpp
index 9eef37a3ae6e..09dc8ed88d2f 100644
--- a/source/Interpreter/OptionGroupWatchpoint.cpp
+++ b/source/Interpreter/OptionGroupWatchpoint.cpp
@@ -40,8 +40,8 @@ static OptionEnumValueElement g_watch_size[] =
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "watch", 'w', required_argument, g_watch_type, 0, eArgTypeWatchType, "Specify the type of watching to perform."},
- { LLDB_OPT_SET_1, false, "xsize", 'x', required_argument, g_watch_size, 0, eArgTypeByteSize, "Number of bytes to use to watch a region."}
+ { 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."}
};
diff --git a/source/Interpreter/OptionValueFileSpec.cpp b/source/Interpreter/OptionValueFileSpec.cpp
index e56b48b5579d..3d2a7ff3307a 100644
--- a/source/Interpreter/OptionValueFileSpec.cpp
+++ b/source/Interpreter/OptionValueFileSpec.cpp
@@ -84,17 +84,21 @@ OptionValueFileSpec::SetValueFromCString (const char *value_cstr,
case eVarSetOperationAssign:
if (value_cstr && value_cstr[0])
{
- Args args(value_cstr);
- if (args.GetArgumentCount() == 1)
- {
- const char *path = args.GetArgumentAtIndex(0);
- m_value_was_set = true;
- m_current_value.SetFile(path, true);
- }
- else
- {
- error.SetErrorString("please supply a single path argument for this file or quote the path if it contains spaces");
- }
+ // The setting value may have whitespace, double-quotes, or single-quotes around the file
+ // path to indicate that internal spaces are not word breaks. Strip off any ws & quotes
+ // from the start and end of the file path - we aren't doing any word // breaking here so
+ // the quoting is unnecessary. NB this will cause a problem if someone tries to specify
+ // a file path that legitimately begins or ends with a " or ' character, or whitespace.
+ std::string filepath(value_cstr);
+ auto prefix_chars_to_trim = filepath.find_first_not_of ("\"' \t");
+ if (prefix_chars_to_trim != std::string::npos && prefix_chars_to_trim > 0)
+ filepath.erase(0, prefix_chars_to_trim);
+ auto suffix_chars_to_trim = filepath.find_last_not_of ("\"' \t");
+ if (suffix_chars_to_trim != std::string::npos && suffix_chars_to_trim < filepath.size())
+ filepath.erase (suffix_chars_to_trim + 1);
+
+ m_value_was_set = true;
+ m_current_value.SetFile(filepath.c_str(), true);
}
else
{
diff --git a/source/Interpreter/OptionValueProperties.cpp b/source/Interpreter/OptionValueProperties.cpp
index 0df378235cfa..abee55d93efa 100644
--- a/source/Interpreter/OptionValueProperties.cpp
+++ b/source/Interpreter/OptionValueProperties.cpp
@@ -651,6 +651,7 @@ lldb::OptionValueSP
OptionValueProperties::DeepCopy () const
{
assert(!"this shouldn't happen");
+ return lldb::OptionValueSP();
}
const Property *
diff --git a/source/Interpreter/Options.cpp b/source/Interpreter/Options.cpp
index 293d75356630..8d245cc15daa 100644
--- a/source/Interpreter/Options.cpp
+++ b/source/Interpreter/Options.cpp
@@ -256,7 +256,7 @@ Options::NumCommandOptions ()
return i;
}
-struct option *
+Option *
Options::GetLongOptions ()
{
// Check to see if this has already been done.
@@ -444,13 +444,13 @@ PrintOption (const OptionDefinition &opt_def,
strm.Printf ("--%s", opt_def.long_option);
switch (opt_def.option_has_arg)
{
- case no_argument:
+ case OptionParser::eNoArgument:
break;
- case required_argument:
+ case OptionParser::eRequiredArgument:
strm.Printf (" <%s>", CommandObject::GetArgumentName (opt_def.argument_type));
break;
- case optional_argument:
+ case OptionParser::eOptionalArgument:
strm.Printf ("%s[<%s>]",
show_short_option ? "" : "=",
CommandObject::GetArgumentName (opt_def.argument_type));
@@ -529,7 +529,7 @@ Options::GenerateOptionUsage
// Add current option to the end of out_stream.
if (opt_defs[i].required == true &&
- opt_defs[i].option_has_arg == no_argument)
+ opt_defs[i].option_has_arg == OptionParser::eNoArgument)
{
options.insert (opt_defs[i].short_option);
}
@@ -560,7 +560,7 @@ Options::GenerateOptionUsage
// Add current option to the end of out_stream.
if (opt_defs[i].required == false &&
- opt_defs[i].option_has_arg == no_argument)
+ opt_defs[i].option_has_arg == OptionParser::eNoArgument)
{
options.insert (opt_defs[i].short_option);
}
@@ -591,7 +591,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 != no_argument)
+ if (opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument)
PrintOption (opt_defs[i], eDisplayBestOption, " ", NULL, true, strm);
}
}
@@ -604,7 +604,7 @@ Options::GenerateOptionUsage
{
// Add current option to the end of out_stream.
- if (!opt_defs[i].required && opt_defs[i].option_has_arg != no_argument)
+ if (!opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument)
PrintOption (opt_defs[i], eDisplayBestOption, " ", NULL, true, strm);
}
}
@@ -992,6 +992,18 @@ OptionGroupOptions::Append (OptionGroup* group)
}
}
+const OptionGroup*
+OptionGroupOptions::GetGroupWithOption (char short_opt)
+{
+ for (uint32_t i = 0; i < m_option_defs.size(); i++)
+ {
+ OptionDefinition opt_def = m_option_defs[i];
+ if (opt_def.short_option == short_opt)
+ return m_option_infos[i].option_group;
+ }
+ return NULL;
+}
+
void
OptionGroupOptions::Append (OptionGroup* group,
uint32_t src_mask,
diff --git a/source/Interpreter/PythonDataObjects.cpp b/source/Interpreter/PythonDataObjects.cpp
index 2a1f348e14b7..da4e085e2398 100644
--- a/source/Interpreter/PythonDataObjects.cpp
+++ b/source/Interpreter/PythonDataObjects.cpp
@@ -93,18 +93,22 @@ PythonObject::Str ()
//----------------------------------------------------------------------
PythonString::PythonString (PyObject *py_obj) :
- PythonObject(py_obj)
+ PythonObject()
{
+ Reset(py_obj); // Use "Reset()" to ensure that py_obj is a string
}
PythonString::PythonString (const PythonObject &object) :
- PythonObject(object.GetPythonObject())
+ PythonObject()
{
+ Reset(object.GetPythonObject()); // Use "Reset()" to ensure that py_obj is a string
}
PythonString::PythonString (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
- PythonObject (script_object_sp)
+ PythonObject()
{
+ if (script_object_sp)
+ Reset((PyObject *)script_object_sp->GetObject()); // Use "Reset()" to ensure that py_obj is a string
}
PythonString::PythonString (const char* string) :
@@ -158,23 +162,28 @@ PythonString::SetString (const char* string)
//----------------------------------------------------------------------
PythonInteger::PythonInteger (PyObject *py_obj) :
- PythonObject(py_obj)
+ PythonObject()
{
+ Reset(py_obj); // Use "Reset()" to ensure that py_obj is a integer type
}
PythonInteger::PythonInteger (const PythonObject &object) :
- PythonObject(object.GetPythonObject())
+ PythonObject()
{
+ Reset(object.GetPythonObject()); // Use "Reset()" to ensure that py_obj is a integer type
}
PythonInteger::PythonInteger (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
- PythonObject (script_object_sp)
+ PythonObject()
{
+ if (script_object_sp)
+ Reset((PyObject *)script_object_sp->GetObject()); // Use "Reset()" to ensure that py_obj is a string
}
PythonInteger::PythonInteger (int64_t value) :
- PythonObject(PyInt_FromLong(value))
+ PythonObject()
{
+ SetInteger (value);
}
@@ -185,8 +194,11 @@ PythonInteger::~PythonInteger ()
bool
PythonInteger::Reset (PyObject *py_obj)
{
- if (py_obj && PyInt_Check(py_obj))
- return PythonObject::Reset(py_obj);
+ if (py_obj)
+ {
+ if (PyInt_Check (py_obj) || PyLong_Check(py_obj))
+ return PythonObject::Reset(py_obj);
+ }
PythonObject::Reset(NULL);
return py_obj == NULL;
@@ -196,15 +208,19 @@ int64_t
PythonInteger::GetInteger()
{
if (m_py_obj)
- return PyInt_AsLong(m_py_obj);
- else
- return UINT64_MAX;
+ {
+ if (PyInt_Check(m_py_obj))
+ return PyInt_AsLong(m_py_obj);
+ else if (PyLong_Check(m_py_obj))
+ return PyLong_AsLongLong(m_py_obj);
+ }
+ return UINT64_MAX;
}
void
PythonInteger::SetInteger (int64_t value)
{
- PythonObject::Reset(PyInt_FromLong(value));
+ PythonObject::Reset(PyLong_FromLongLong(value));
}
//----------------------------------------------------------------------
@@ -222,19 +238,23 @@ PythonList::PythonList (uint32_t count) :
}
PythonList::PythonList (PyObject *py_obj) :
- PythonObject(py_obj)
+ PythonObject()
{
+ Reset(py_obj); // Use "Reset()" to ensure that py_obj is a list
}
PythonList::PythonList (const PythonObject &object) :
- PythonObject(object.GetPythonObject())
+ PythonObject()
{
+ Reset(object.GetPythonObject()); // Use "Reset()" to ensure that py_obj is a list
}
PythonList::PythonList (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
- PythonObject (script_object_sp)
+ PythonObject()
{
+ if (script_object_sp)
+ Reset((PyObject *)script_object_sp->GetObject()); // Use "Reset()" to ensure that py_obj is a list
}
PythonList::~PythonList ()
@@ -293,17 +313,21 @@ PythonDictionary::PythonDictionary () :
PythonDictionary::PythonDictionary (PyObject *py_obj) :
PythonObject(py_obj)
{
+ Reset(py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
}
PythonDictionary::PythonDictionary (const PythonObject &object) :
- PythonObject(object.GetPythonObject())
+ PythonObject()
{
+ Reset(object.GetPythonObject()); // Use "Reset()" to ensure that py_obj is a dictionary
}
PythonDictionary::PythonDictionary (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
- PythonObject (script_object_sp)
+ PythonObject ()
{
+ if (script_object_sp)
+ Reset((PyObject *)script_object_sp->GetObject()); // Use "Reset()" to ensure that py_obj is a dictionary
}
PythonDictionary::~PythonDictionary ()
diff --git a/source/Interpreter/ScriptInterpreter.cpp b/source/Interpreter/ScriptInterpreter.cpp
index 67314731df2a..1b751afb135e 100644
--- a/source/Interpreter/ScriptInterpreter.cpp
+++ b/source/Interpreter/ScriptInterpreter.cpp
@@ -88,10 +88,48 @@ ScriptInterpreter::AcquireInterpreterLock ()
}
void
-ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_callback)
+ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
+ SWIGBreakpointCallbackFunction swig_breakpoint_callback,
+ SWIGWatchpointCallbackFunction swig_watchpoint_callback,
+ SWIGPythonTypeScriptCallbackFunction swig_typescript_callback,
+ SWIGPythonCreateSyntheticProvider swig_synthetic_script,
+ SWIGPythonCalculateNumChildren swig_calc_children,
+ SWIGPythonGetChildAtIndex swig_get_child_index,
+ SWIGPythonGetIndexOfChildWithName swig_get_index_child,
+ SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue ,
+ SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
+ SWIGPythonUpdateSynthProviderInstance swig_update_provider,
+ SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
+ SWIGPythonCallCommand swig_call_command,
+ SWIGPythonCallModuleInit swig_call_module_init,
+ SWIGPythonCreateOSPlugin swig_create_os_plugin,
+ SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
+ SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
+ SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
+ SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
+ SWIGPython_GetDynamicSetting swig_plugin_get)
{
#ifndef LLDB_DISABLE_PYTHON
- ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback);
+ ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback,
+ swig_breakpoint_callback,
+ swig_watchpoint_callback,
+ swig_typescript_callback,
+ swig_synthetic_script,
+ swig_calc_children,
+ swig_get_child_index,
+ swig_get_index_child,
+ swig_cast_to_sbvalue ,
+ swig_get_valobj_sp_from_sbvalue,
+ swig_update_provider,
+ swig_mighthavechildren_provider,
+ swig_call_command,
+ swig_call_module_init,
+ swig_create_os_plugin,
+ swig_run_script_keyword_process,
+ swig_run_script_keyword_thread,
+ swig_run_script_keyword_target,
+ swig_run_script_keyword_frame,
+ swig_plugin_get);
#endif // #ifndef LLDB_DISABLE_PYTHON
}
diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp
index 9d9b8d93fb4d..fc76f0470d3a 100644
--- a/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/source/Interpreter/ScriptInterpreterPython.cpp
@@ -52,6 +52,7 @@ static ScriptInterpreter::SWIGPythonCalculateNumChildren g_swig_calc_children =
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;
@@ -61,95 +62,7 @@ static ScriptInterpreter::SWIGPythonScriptKeyword_Process g_swig_run_script_keyw
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;
-
-// these are the Pythonic implementations of the required callbacks
-// these are scripting-language specific, which is why they belong here
-// we still need to use function pointers to them instead of relying
-// on linkage-time resolution because the SWIG stuff and this file
-// get built at different times
-extern "C" bool
-LLDBSwigPythonBreakpointCallbackFunction (const char *python_function_name,
- const char *session_dictionary_name,
- const lldb::StackFrameSP& sb_frame,
- const lldb::BreakpointLocationSP& sb_bp_loc);
-
-extern "C" bool
-LLDBSwigPythonWatchpointCallbackFunction (const char *python_function_name,
- const char *session_dictionary_name,
- const lldb::StackFrameSP& sb_frame,
- const lldb::WatchpointSP& sb_wp);
-
-extern "C" bool
-LLDBSwigPythonCallTypeScript (const char *python_function_name,
- void *session_dictionary,
- const lldb::ValueObjectSP& valobj_sp,
- void** pyfunct_wrapper,
- std::string& retval);
-
-extern "C" void*
-LLDBSwigPythonCreateSyntheticProvider (const char *python_class_name,
- const char *session_dictionary_name,
- const lldb::ValueObjectSP& valobj_sp);
-
-
-extern "C" uint32_t
-LLDBSwigPython_CalculateNumChildren (void *implementor);
-
-extern "C" void *
-LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx);
-
-extern "C" int
-LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name);
-
-extern "C" void *
-LLDBSWIGPython_CastPyObjectToSBValue (void* data);
-
-extern "C" bool
-LLDBSwigPython_UpdateSynthProviderInstance (void* implementor);
-
-extern "C" bool
-LLDBSwigPython_MightHaveChildrenSynthProviderInstance (void* implementor);
-
-extern "C" bool
-LLDBSwigPythonCallCommand (const char *python_function_name,
- const char *session_dictionary_name,
- lldb::DebuggerSP& debugger,
- const char* args,
- lldb_private::CommandReturnObject &cmd_retobj);
-
-extern "C" bool
-LLDBSwigPythonCallModuleInit (const char *python_module_name,
- const char *session_dictionary_name,
- lldb::DebuggerSP& debugger);
-
-extern "C" void*
-LLDBSWIGPythonCreateOSPlugin (const char *python_class_name,
- const char *session_dictionary_name,
- const lldb::ProcessSP& process_sp);
-
-extern "C" bool
-LLDBSWIGPythonRunScriptKeywordProcess (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::ProcessSP& process,
- std::string& output);
-
-extern "C" bool
-LLDBSWIGPythonRunScriptKeywordThread (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::ThreadSP& thread,
- std::string& output);
-
-extern "C" bool
-LLDBSWIGPythonRunScriptKeywordTarget (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::TargetSP& target,
- std::string& output);
-
-extern "C" bool
-LLDBSWIGPythonRunScriptKeywordFrame (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::StackFrameSP& frame,
- std::string& output);
+static ScriptInterpreter::SWIGPython_GetDynamicSetting g_swig_plugin_get = NULL;
static int
_check_and_flush (FILE *stream)
@@ -418,7 +331,7 @@ ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback (void *ba
if (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor() != -1)
{
if (log)
- log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, GotToken, bytes='%s', byte_len = %lu", bytes,
+ log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, GotToken, bytes='%s', byte_len = %zu", bytes,
bytes_len);
if (bytes && bytes_len)
::write (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor(), bytes, bytes_len);
@@ -427,7 +340,7 @@ ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback (void *ba
else
{
if (log)
- log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, GotToken, bytes='%s', byte_len = %lu, Master File Descriptor is bad.",
+ log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, GotToken, bytes='%s', byte_len = %zu, Master File Descriptor is bad.",
bytes,
bytes_len);
reader.SetIsDone (true);
@@ -954,7 +867,7 @@ ScriptInterpreterPython::InputReaderCallback
if (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor() != -1)
{
if (log)
- log->Printf ("ScriptInterpreterPython::InputReaderCallback, GotToken, bytes='%s', byte_len = %lu", bytes,
+ log->Printf ("ScriptInterpreterPython::InputReaderCallback, GotToken, bytes='%s', byte_len = %zu", bytes,
bytes_len);
if (bytes && bytes_len)
{
@@ -968,7 +881,7 @@ ScriptInterpreterPython::InputReaderCallback
else
{
if (log)
- log->Printf ("ScriptInterpreterPython::InputReaderCallback, GotToken, bytes='%s', byte_len = %lu, Master File Descriptor is bad.",
+ log->Printf ("ScriptInterpreterPython::InputReaderCallback, GotToken, bytes='%s', byte_len = %zu, Master File Descriptor is bad.",
bytes,
bytes_len);
reader.SetIsDone (true);
@@ -1176,6 +1089,13 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
success = PyArg_Parse (py_return, format, (char *) ret_value);
break;
}
+ case eScriptReturnTypeOpaqueObject:
+ {
+ success = true;
+ Py_XINCREF(py_return);
+ *((PyObject**)ret_value) = py_return;
+ break;
+ }
}
Py_XDECREF (py_return);
if (success)
@@ -2064,6 +1984,47 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP
}
lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::LoadPluginModule (const FileSpec& file_spec,
+ lldb_private::Error& error)
+{
+ if (!file_spec.Exists())
+ {
+ error.SetErrorString("no such file");
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ ScriptInterpreterObjectSP module_sp;
+
+ if (LoadScriptingModule(file_spec.GetPath().c_str(),true,true,error,&module_sp))
+ return module_sp;
+
+ return lldb::ScriptInterpreterObjectSP();
+}
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::GetDynamicSettings (lldb::ScriptInterpreterObjectSP plugin_module_sp,
+ Target* target,
+ const char* setting_name,
+ lldb_private::Error& error)
+{
+ if (!plugin_module_sp || !target || !setting_name || !setting_name[0])
+ return lldb::ScriptInterpreterObjectSP();
+
+ if (!g_swig_plugin_get)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject *reply_pyobj = nullptr;
+
+ {
+ Locker py_lock(this);
+ TargetSP target_sp(target->shared_from_this());
+ reply_pyobj = (PyObject*)g_swig_plugin_get(plugin_module_sp->GetObject(),setting_name,target_sp);
+ }
+
+ return MakeScriptObject(reply_pyobj);
+}
+
+lldb::ScriptInterpreterObjectSP
ScriptInterpreterPython::CreateSyntheticScriptedProvider (const char *class_name,
lldb::ValueObjectSP valobj)
{
@@ -2451,20 +2412,18 @@ ScriptInterpreterPython::GetChildAtIndex (const lldb::ScriptInterpreterObjectSP&
if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue)
return lldb::ValueObjectSP();
- void* child_ptr = NULL;
- lldb::SBValue* value_sb = NULL;
lldb::ValueObjectSP ret_val;
{
Locker py_lock(this);
- child_ptr = g_swig_get_child_index (implementor,idx);
+ void* child_ptr = g_swig_get_child_index (implementor,idx);
if (child_ptr != NULL && child_ptr != Py_None)
{
- value_sb = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
- if (value_sb == NULL)
+ lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
+ if (sb_value_ptr == NULL)
Py_XDECREF(child_ptr);
else
- ret_val = value_sb->GetSP();
+ ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr);
}
else
{
@@ -2749,7 +2708,8 @@ bool
ScriptInterpreterPython::LoadScriptingModule (const char* pathname,
bool can_reload,
bool init_session,
- lldb_private::Error& error)
+ lldb_private::Error& error,
+ lldb::ScriptInterpreterObjectSP* module_sp)
{
if (!pathname || !pathname[0])
{
@@ -2914,6 +2874,17 @@ ScriptInterpreterPython::LoadScriptingModule (const char* pathname,
error.SetErrorString("calling __lldb_init_module failed");
return false;
}
+
+ if (module_sp)
+ {
+ // everything went just great, now set the module object
+ command_stream.Clear();
+ command_stream.Printf("%s",basename.c_str());
+ void* module_pyobj = nullptr;
+ if (ExecuteOneLineWithReturn(command_stream.GetData(),ScriptInterpreter::eScriptReturnTypeOpaqueObject,&module_pyobj) && module_pyobj)
+ *module_sp = MakeScriptObject(module_pyobj);
+ }
+
return true;
}
}
@@ -3047,26 +3018,47 @@ ScriptInterpreterPython::AcquireInterpreterLock ()
}
void
-ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_init_callback)
-{
- g_swig_init_callback = python_swig_init_callback;
- g_swig_breakpoint_callback = LLDBSwigPythonBreakpointCallbackFunction;
- g_swig_watchpoint_callback = LLDBSwigPythonWatchpointCallbackFunction;
- g_swig_typescript_callback = LLDBSwigPythonCallTypeScript;
- g_swig_synthetic_script = LLDBSwigPythonCreateSyntheticProvider;
- g_swig_calc_children = LLDBSwigPython_CalculateNumChildren;
- g_swig_get_child_index = LLDBSwigPython_GetChildAtIndex;
- g_swig_get_index_child = LLDBSwigPython_GetIndexOfChildWithName;
- g_swig_cast_to_sbvalue = LLDBSWIGPython_CastPyObjectToSBValue;
- g_swig_update_provider = LLDBSwigPython_UpdateSynthProviderInstance;
- g_swig_mighthavechildren_provider = LLDBSwigPython_MightHaveChildrenSynthProviderInstance;
- g_swig_call_command = LLDBSwigPythonCallCommand;
- g_swig_call_module_init = LLDBSwigPythonCallModuleInit;
- g_swig_create_os_plugin = LLDBSWIGPythonCreateOSPlugin;
- g_swig_run_script_keyword_process = LLDBSWIGPythonRunScriptKeywordProcess;
- g_swig_run_script_keyword_thread = LLDBSWIGPythonRunScriptKeywordThread;
- g_swig_run_script_keyword_target = LLDBSWIGPythonRunScriptKeywordTarget;
- g_swig_run_script_keyword_frame = LLDBSWIGPythonRunScriptKeywordFrame;
+ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callback,
+ SWIGBreakpointCallbackFunction swig_breakpoint_callback,
+ SWIGWatchpointCallbackFunction swig_watchpoint_callback,
+ SWIGPythonTypeScriptCallbackFunction swig_typescript_callback,
+ SWIGPythonCreateSyntheticProvider swig_synthetic_script,
+ SWIGPythonCalculateNumChildren swig_calc_children,
+ SWIGPythonGetChildAtIndex swig_get_child_index,
+ SWIGPythonGetIndexOfChildWithName swig_get_index_child,
+ SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue ,
+ SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
+ SWIGPythonUpdateSynthProviderInstance swig_update_provider,
+ SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
+ SWIGPythonCallCommand swig_call_command,
+ SWIGPythonCallModuleInit swig_call_module_init,
+ SWIGPythonCreateOSPlugin swig_create_os_plugin,
+ SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
+ SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
+ SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
+ SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
+ SWIGPython_GetDynamicSetting swig_plugin_get)
+{
+ g_swig_init_callback = swig_init_callback;
+ g_swig_breakpoint_callback = swig_breakpoint_callback;
+ g_swig_watchpoint_callback = swig_watchpoint_callback;
+ g_swig_typescript_callback = swig_typescript_callback;
+ g_swig_synthetic_script = swig_synthetic_script;
+ g_swig_calc_children = swig_calc_children;
+ g_swig_get_child_index = swig_get_child_index;
+ g_swig_get_index_child = swig_get_index_child;
+ g_swig_cast_to_sbvalue = swig_cast_to_sbvalue;
+ g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue;
+ g_swig_update_provider = swig_update_provider;
+ g_swig_mighthavechildren_provider = swig_mighthavechildren_provider;
+ g_swig_call_command = swig_call_command;
+ g_swig_call_module_init = swig_call_module_init;
+ g_swig_create_os_plugin = swig_create_os_plugin;
+ g_swig_run_script_keyword_process = swig_run_script_keyword_process;
+ g_swig_run_script_keyword_thread = swig_run_script_keyword_thread;
+ g_swig_run_script_keyword_target = swig_run_script_keyword_target;
+ g_swig_run_script_keyword_frame = swig_run_script_keyword_frame;
+ g_swig_plugin_get = swig_plugin_get;
}
void
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
index 4685c3e759e0..f27c294a4abd 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -580,32 +580,13 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
bool
ABIMacOSX_arm::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
{
- uint32_t reg_kind = unwind_plan.GetRegisterKind();
- uint32_t lr_reg_num = LLDB_INVALID_REGNUM;
- uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
- uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
-
- switch (reg_kind)
- {
- case eRegisterKindDWARF:
- case eRegisterKindGCC:
- lr_reg_num = dwarf_lr;
- sp_reg_num = dwarf_sp;
- pc_reg_num = dwarf_pc;
- break;
-
- case eRegisterKindGeneric:
- lr_reg_num = LLDB_REGNUM_GENERIC_RA;
- sp_reg_num = LLDB_REGNUM_GENERIC_SP;
- pc_reg_num = LLDB_REGNUM_GENERIC_PC;
- break;
- }
-
- if (lr_reg_num == LLDB_INVALID_REGNUM ||
- sp_reg_num == LLDB_INVALID_REGNUM ||
- pc_reg_num == LLDB_INVALID_REGNUM)
- return false;
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+ uint32_t lr_reg_num = dwarf_lr;
+ uint32_t sp_reg_num = dwarf_sp;
+ uint32_t pc_reg_num = dwarf_pc;
+
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
@@ -626,14 +607,15 @@ ABIMacOSX_arm::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
bool
ABIMacOSX_arm::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
{
- uint32_t fp_reg_num = dwarf_r7; // apple uses r7 for all frames. Normal arm uses r11;
+ unwind_plan.Clear ();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t fp_reg_num = dwarf_r7; // apple uses r7 for all frames. Normal arm uses r11
uint32_t pc_reg_num = dwarf_pc;
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 4;
- unwind_plan.Clear ();
- unwind_plan.SetRegisterKind (eRegisterKindDWARF);
row->SetCFARegister (fp_reg_num);
row->SetCFAOffset (2 * ptr_size);
row->SetOffset (0);
@@ -649,6 +631,11 @@ ABIMacOSX_arm::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
return true;
}
+// cf. "ARMv6 Function Calling Conventions"
+// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html
+// and "ARMv7 Function Calling Conventions"
+// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv7FunctionCallingConventions.html
+
// ARMv7 on iOS general purpose reg rules:
// r0-r3 not preserved (used for argument passing)
// r4-r6 preserved
@@ -672,7 +659,7 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info)
{
if (reg_info)
{
- // Volatile registers include: r0, r1, r2, r3, r9, r12, r13
+ // Volatile registers are: r0, r1, r2, r3, r9, r12, r13 (aka sp)
const char *name = reg_info->name;
if (name[0] == 'r')
{
@@ -686,7 +673,7 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info)
return true; // r1
case '2':
case '3':
- return name[2] == '\0'; // r12 - r13
+ return name[3] == '\0'; // r12, r13 (sp)
default:
break;
}
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index deb531d937a0..ecf44b9c4f73 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -235,12 +235,22 @@ ABIMacOSX_i386::GetRedZoneSize () const
ABISP
ABIMacOSX_i386::CreateInstance (const ArchSpec &arch)
{
- static ABISP g_abi_sp;
+ static ABISP g_abi_mac_sp;
+ static ABISP g_abi_other_sp;
if (arch.GetTriple().getArch() == llvm::Triple::x86)
{
- if (!g_abi_sp)
- g_abi_sp.reset (new ABIMacOSX_i386);
- return g_abi_sp;
+ if (arch.GetTriple().isOSDarwin())
+ {
+ if (!g_abi_mac_sp)
+ g_abi_mac_sp.reset (new ABIMacOSX_i386(true));
+ return g_abi_mac_sp;
+ }
+ else
+ {
+ if (!g_abi_other_sp)
+ g_abi_other_sp.reset (new ABIMacOSX_i386(false));
+ return g_abi_other_sp;
+ }
}
return ABISP();
}
@@ -823,37 +833,12 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
bool
ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
{
- uint32_t reg_kind = unwind_plan.GetRegisterKind();
- uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
- uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
-
- switch (reg_kind)
- {
- case eRegisterKindDWARF:
- sp_reg_num = dwarf_esp;
- pc_reg_num = dwarf_eip;
- break;
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- case eRegisterKindGCC:
- sp_reg_num = gcc_esp;
- pc_reg_num = gcc_eip;
- break;
-
- case eRegisterKindGDB:
- sp_reg_num = gdb_esp;
- pc_reg_num = gdb_eip;
- break;
-
- case eRegisterKindGeneric:
- sp_reg_num = LLDB_REGNUM_GENERIC_SP;
- pc_reg_num = LLDB_REGNUM_GENERIC_PC;
- break;
- }
+ uint32_t sp_reg_num = dwarf_esp;
+ uint32_t pc_reg_num = dwarf_eip;
- if (sp_reg_num == LLDB_INVALID_REGNUM ||
- pc_reg_num == LLDB_INVALID_REGNUM)
- return false;
-
UnwindPlan::RowSP row(new UnwindPlan::Row);
row->SetCFARegister (sp_reg_num);
row->SetCFAOffset (4);
@@ -867,6 +852,9 @@ ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
bool
ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
{
+ unwind_plan.Clear ();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
uint32_t fp_reg_num = dwarf_ebp;
uint32_t sp_reg_num = dwarf_esp;
uint32_t pc_reg_num = dwarf_eip;
@@ -874,15 +862,13 @@ ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 4;
- unwind_plan.Clear ();
- unwind_plan.SetRegisterKind (eRegisterKindDWARF);
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);
- row->SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size * 0, true);
+ row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("i386 default unwind plan");
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
index 8c2d945e6342..5428d0c1e44e 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
@@ -79,9 +79,21 @@ public:
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
+ // Darwin call frame addresses must be 16-byte aligned, but other OS's
+ // only need 4-byte alignment. Otherwise the ABI matches, so we have
+ // this one minor override here.
+ if (target_is_darwin)
+ {
+ // Make sure the stack call frame addresses are are 16 byte aligned
+ if (cfa & (16ull - 1ull))
+ return false; // Not 16 byte aligned
+ }
+ else
+ {
+ // Make sure the stack call frame addresses are are 4 byte aligned
+ if (cfa & (4ull - 1ull))
+ return false; // Not 4 byte aligned
+ }
if (cfa == 0)
return false; // Zero is not a valid stack address
return true;
@@ -132,7 +144,11 @@ protected:
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABIMacOSX_i386() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABIMacOSX_i386(bool is_darwin) : lldb_private::ABI(),
+ target_is_darwin(is_darwin)
+ { } // Call CreateInstance instead.
+
+ bool target_is_darwin;
};
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 a904d8b649ca..a8cf714a13b3 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -354,7 +354,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
const RegisterInfo *reg_info = NULL;
if (arg1_ptr)
{
- reg_info = reg_ctx->GetRegisterInfoByName("rdi", 0);
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
if (log)
log->Printf("About to write arg1 (0x%" PRIx64 ") into %s", (uint64_t)*arg1_ptr, reg_info->name);
@@ -363,7 +363,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
if (arg2_ptr)
{
- reg_info = reg_ctx->GetRegisterInfoByName("rsi", 0);
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
if (log)
log->Printf("About to write arg2 (0x%" PRIx64 ") into %s", (uint64_t)*arg2_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg2_ptr))
@@ -371,7 +371,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
if (arg3_ptr)
{
- reg_info = reg_ctx->GetRegisterInfoByName("rdx", 0);
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3);
if (log)
log->Printf("About to write arg3 (0x%" PRIx64 ") into %s", (uint64_t)*arg3_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg3_ptr))
@@ -379,7 +379,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
if (arg4_ptr)
{
- reg_info = reg_ctx->GetRegisterInfoByName("rcx", 0);
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4);
if (log)
log->Printf("About to write arg4 (0x%" PRIx64 ") into %s", (uint64_t)*arg4_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg4_ptr))
@@ -387,7 +387,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
if (arg5_ptr)
{
- reg_info = reg_ctx->GetRegisterInfoByName("r8", 0);
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5);
if (log)
log->Printf("About to write arg5 (0x%" PRIx64 ") into %s", (uint64_t)*arg5_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg5_ptr))
@@ -395,7 +395,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
if (arg6_ptr)
{
- reg_info = reg_ctx->GetRegisterInfoByName("r9", 0);
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6);
if (log)
log->Printf("About to write arg6 (0x%" PRIx64 ") into %s", (uint64_t)*arg6_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg6_ptr))
@@ -415,32 +415,75 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
sp &= ~(0xfull); // 16-byte alignment
- // The return address is pushed onto the stack (yes after the alignment...)
sp -= 8;
+ Error error;
+ const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ ProcessSP process_sp (thread.GetProcess());
+
RegisterValue reg_value;
- reg_value.SetUInt64 (return_addr);
+#if 0
+ // This code adds an extra frame so that we don't lose the function that we came from
+ // by pushing the PC and the FP and then writing the current FP to point to the FP value
+ // we just pushed. It is disabled for now until the stack backtracing code can be debugged.
+
+ // Save current PC
+ const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+ if (reg_ctx->ReadRegister(pc_reg_info, reg_value))
+ {
+ if (log)
+ log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64());
+
+ if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error))
+ return false;
+
+ sp -= 8;
+
+ // Save current FP
+ if (reg_ctx->ReadRegister(fp_reg_info, reg_value))
+ {
+ if (log)
+ log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64());
+
+ if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error))
+ return false;
+ }
+ // Setup FP backchain
+ reg_value.SetUInt64 (sp);
+
+ if (log)
+ log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64());
+
+ if (!reg_ctx->WriteRegister(fp_reg_info, reg_value))
+ {
+ return false;
+ }
+
+ sp -= 8;
+ }
+#endif
+
if (log)
- log->Printf("Pushing the return address onto the stack: new SP 0x%" PRIx64 ", return address 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr);
+ log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr);
- const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfoByName("rip");
- Error error (reg_ctx->WriteRegisterValueToMemory(pc_reg_info, sp, pc_reg_info->byte_size, reg_value));
- if (error.Fail())
+ // Save return address onto the stack
+ if (!process_sp->WritePointerToMemory(sp, return_addr, error))
return false;
// %rsp is set to the actual stack value.
if (log)
- log->Printf("Writing SP (0x%" PRIx64 ") down", (uint64_t)sp);
+ log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
- if (!reg_ctx->WriteRegisterFromUnsigned (reg_ctx->GetRegisterInfoByName("rsp"), sp))
+ if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp))
return false;
// %rip is set to the address of the called function.
if (log)
- log->Printf("Writing new IP (0x%" PRIx64 ") down", (uint64_t)func_addr);
+ log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr);
if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
return false;
@@ -506,12 +549,12 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread,
uint32_t argument_register_ids[6];
- argument_register_ids[0] = reg_ctx->GetRegisterInfoByName("rdi", 0)->kinds[eRegisterKindLLDB];
- argument_register_ids[1] = reg_ctx->GetRegisterInfoByName("rsi", 0)->kinds[eRegisterKindLLDB];
- argument_register_ids[2] = reg_ctx->GetRegisterInfoByName("rdx", 0)->kinds[eRegisterKindLLDB];
- argument_register_ids[3] = reg_ctx->GetRegisterInfoByName("rcx", 0)->kinds[eRegisterKindLLDB];
- argument_register_ids[4] = reg_ctx->GetRegisterInfoByName("r8", 0)->kinds[eRegisterKindLLDB];
- argument_register_ids[5] = reg_ctx->GetRegisterInfoByName("r9", 0)->kinds[eRegisterKindLLDB];
+ argument_register_ids[0] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)->kinds[eRegisterKindLLDB];
+ argument_register_ids[1] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)->kinds[eRegisterKindLLDB];
+ argument_register_ids[2] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)->kinds[eRegisterKindLLDB];
+ argument_register_ids[3] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)->kinds[eRegisterKindLLDB];
+ argument_register_ids[4] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5)->kinds[eRegisterKindLLDB];
+ argument_register_ids[5] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6)->kinds[eRegisterKindLLDB];
unsigned int current_argument_register = 0;
@@ -1085,33 +1128,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
bool
ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
{
- uint32_t reg_kind = unwind_plan.GetRegisterKind();
- uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
- uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t sp_reg_num = gcc_dwarf_rsp;
+ uint32_t pc_reg_num = gcc_dwarf_rip;
- switch (reg_kind)
- {
- case eRegisterKindDWARF:
- case eRegisterKindGCC:
- sp_reg_num = gcc_dwarf_rsp;
- pc_reg_num = gcc_dwarf_rip;
- break;
-
- case eRegisterKindGDB:
- sp_reg_num = gdb_rsp;
- pc_reg_num = gdb_rip;
- break;
-
- case eRegisterKindGeneric:
- sp_reg_num = LLDB_REGNUM_GENERIC_SP;
- pc_reg_num = LLDB_REGNUM_GENERIC_PC;
- break;
- }
-
- if (sp_reg_num == LLDB_INVALID_REGNUM ||
- pc_reg_num == LLDB_INVALID_REGNUM)
- return false;
-
UnwindPlan::RowSP row(new UnwindPlan::Row);
row->SetCFARegister (sp_reg_num);
row->SetCFAOffset (8);
@@ -1125,48 +1147,23 @@ ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
bool
ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
{
- uint32_t reg_kind = unwind_plan.GetRegisterKind();
- uint32_t fp_reg_num = LLDB_INVALID_REGNUM;
- uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
- uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
-
- switch (reg_kind)
- {
- case eRegisterKindDWARF:
- case eRegisterKindGCC:
- fp_reg_num = gcc_dwarf_rbp;
- sp_reg_num = gcc_dwarf_rsp;
- pc_reg_num = gcc_dwarf_rip;
- break;
-
- case eRegisterKindGDB:
- fp_reg_num = gdb_rbp;
- sp_reg_num = gdb_rsp;
- pc_reg_num = gdb_rip;
- break;
-
- case eRegisterKindGeneric:
- fp_reg_num = LLDB_REGNUM_GENERIC_FP;
- sp_reg_num = LLDB_REGNUM_GENERIC_SP;
- pc_reg_num = LLDB_REGNUM_GENERIC_PC;
- break;
- }
-
- if (fp_reg_num == LLDB_INVALID_REGNUM ||
- sp_reg_num == LLDB_INVALID_REGNUM ||
- pc_reg_num == LLDB_INVALID_REGNUM)
- return false;
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+ uint32_t fp_reg_num = gcc_dwarf_rbp;
+ uint32_t sp_reg_num = gcc_dwarf_rsp;
+ uint32_t pc_reg_num = gcc_dwarf_rip;
+
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 8;
- row->SetCFARegister (LLDB_REGNUM_GENERIC_FP);
+ row->SetCFARegister (gcc_dwarf_rbp);
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);
- row->SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size * 0, true);
+ row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("x86_64 default unwind plan");
diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
index b10181960e89..d9d6fd7af79a 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
@@ -76,9 +76,9 @@ public:
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
+ // Make sure the stack call frame addresses are 16 byte aligned
+ if (cfa & (16ull - 1ull))
+ return false; // Not 16 byte aligned
if (cfa == 0)
return false; // Zero is not a valid stack address
return true;
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index e920d70cd596..61c3c64d4fc3 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -38,7 +38,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/StackFrame.h"
-#include <regex.h>
+#include "lldb/Core/RegularExpression.h"
using namespace lldb;
using namespace lldb_private;
@@ -369,20 +369,14 @@ public:
}
}
- if (!s_regex_compiled)
- {
- ::regcomp(&s_regex, "[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED);
- s_regex_compiled = true;
- }
+ static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED);
- ::regmatch_t matches[3];
+ RegularExpression::Match matches(3);
- if (!::regexec(&s_regex, out_string, sizeof(matches) / sizeof(::regmatch_t), matches, 0))
+ if (s_regex.Execute(out_string, &matches))
{
- if (matches[1].rm_so != -1)
- m_opcode_name.assign(out_string + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
- if (matches[2].rm_so != -1)
- m_mnemonics.assign(out_string + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
+ matches.GetMatchAtIndex(out_string, 1, m_opcode_name);
+ matches.GetMatchAtIndex(out_string, 2, m_mnemonics);
}
}
}
@@ -415,13 +409,9 @@ protected:
LazyBool m_does_branch;
bool m_is_valid;
bool m_using_file_addr;
-
- static bool s_regex_compiled;
- static ::regex_t s_regex;
};
-bool InstructionLLVMC::s_regex_compiled = false;
-::regex_t InstructionLLVMC::s_regex;
+
DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner):
m_is_valid(true)
@@ -651,9 +641,15 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
}
// Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions,
- // so hardcode the primary disassembler to thumb mode.
+ // 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.
+
if (arch.GetTriple().getArch() == llvm::Triple::arm
- && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em))
+ && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m
+ || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em
+ || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m))
{
triple = thumb_arch.GetTriple().getTriple().c_str();
}
@@ -796,7 +792,7 @@ int DisassemblerLLVMC::OpInfo (uint64_t PC,
default:
break;
case 1:
- bzero (tag_bug, sizeof(::LLVMOpInfo1));
+ memset (tag_bug, 0, sizeof(::LLVMOpInfo1));
break;
}
return 0;
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
index 2604ae670164..c079d0fc381f 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
@@ -19,7 +19,7 @@
#include "lldb/Core/Log.h"
#include "lldb/Target/Process.h"
-#if defined(__linux__) or defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__)
#include "Plugins/Process/elf-core/ProcessElfCore.h"
#endif
@@ -57,7 +57,7 @@ ParseAuxvEntry(DataExtractor &data,
DataBufferSP
AuxVector::GetAuxvData()
{
-#if defined(__linux__) or defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__)
if (m_process->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
return static_cast<ProcessElfCore *>(m_process)->GetAuxvData();
#endif
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index 3e1b52938f49..3c5dcc5222af 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/Symbol.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -30,17 +31,14 @@ ResolveRendezvousAddress(Process *process)
addr_t info_location;
addr_t info_addr;
Error error;
- size_t size;
info_location = process->GetImageInfoAddress();
if (info_location == LLDB_INVALID_ADDRESS)
return LLDB_INVALID_ADDRESS;
- info_addr = 0;
- size = process->DoReadMemory(info_location, &info_addr,
- process->GetAddressByteSize(), error);
- if (size != process->GetAddressByteSize() || error.Fail())
+ info_addr = process->ReadPointerFromMemory(info_location, error);
+ if (error.Fail())
return LLDB_INVALID_ADDRESS;
if (info_addr == 0)
@@ -58,6 +56,8 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
m_added_soentries(),
m_removed_soentries()
{
+ m_thread_info.valid = false;
+
// Cache a copy of the executable path
if (m_process)
{
@@ -88,19 +88,19 @@ DYLDRendezvous::Resolve()
if (cursor == LLDB_INVALID_ADDRESS)
return false;
- if (!(cursor = ReadMemory(cursor, &info.version, word_size)))
+ if (!(cursor = ReadWord(cursor, &info.version, word_size)))
return false;
- if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size)))
+ if (!(cursor = ReadPointer(cursor + padding, &info.map_addr)))
return false;
- if (!(cursor = ReadMemory(cursor, &info.brk, address_size)))
+ if (!(cursor = ReadPointer(cursor, &info.brk)))
return false;
- if (!(cursor = ReadMemory(cursor, &info.state, word_size)))
+ if (!(cursor = ReadWord(cursor, &info.state, word_size)))
return false;
- if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size)))
+ if (!(cursor = ReadPointer(cursor + padding, &info.ldbase)))
return false;
// The rendezvous was successfully read. Update our internal state.
@@ -234,16 +234,27 @@ DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
}
addr_t
-DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size)
+DYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size)
{
- size_t bytes_read;
Error error;
- bytes_read = m_process->DoReadMemory(addr, dst, size, error);
- if (bytes_read != size || error.Fail())
+ *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error);
+ if (error.Fail())
return 0;
- return addr + bytes_read;
+ return addr + size;
+}
+
+addr_t
+DYLDRendezvous::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
@@ -275,23 +286,38 @@ DYLDRendezvous::ReadStringFromMemory(addr_t addr)
bool
DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
{
- size_t address_size = m_process->GetAddressByteSize();
-
entry.clear();
+
+ entry.link_addr = addr;
- if (!(addr = ReadMemory(addr, &entry.base_addr, address_size)))
+ if (!(addr = ReadPointer(addr, &entry.base_addr)))
return false;
+
+ // mips adds an extra load offset field to the link map struct on
+ // FreeBSD and NetBSD (need to validate other OSes).
+ // http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57
+ const ArchSpec &arch = m_process->GetTarget().GetArchitecture();
+ if (arch.GetCore() == ArchSpec::eCore_mips64)
+ {
+ assert (arch.GetTriple().getOS() == llvm::Triple::FreeBSD ||
+ arch.GetTriple().getOS() == llvm::Triple::NetBSD);
+ addr_t mips_l_offs;
+ if (!(addr = ReadPointer(addr, &mips_l_offs)))
+ return false;
+ if (mips_l_offs != 0 && mips_l_offs != entry.base_addr)
+ return false;
+ }
- if (!(addr = ReadMemory(addr, &entry.path_addr, address_size)))
+ if (!(addr = ReadPointer(addr, &entry.path_addr)))
return false;
- if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size)))
+ if (!(addr = ReadPointer(addr, &entry.dyn_addr)))
return false;
- if (!(addr = ReadMemory(addr, &entry.next, address_size)))
+ if (!(addr = ReadPointer(addr, &entry.next)))
return false;
- if (!(addr = ReadMemory(addr, &entry.prev, address_size)))
+ if (!(addr = ReadPointer(addr, &entry.prev)))
return false;
entry.path = ReadStringFromMemory(entry.path_addr);
@@ -299,6 +325,51 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
return true;
}
+
+bool
+DYLDRendezvous::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 DYLDRendezvous::ThreadInfo&
+DYLDRendezvous::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
DYLDRendezvous::DumpToLog(Log *log) const
{
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
index 67e7228a38de..ca0089317998 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -48,6 +48,16 @@ class DYLDRendezvous {
};
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
+ };
+
DYLDRendezvous(lldb_private::Process *process);
/// Update the internal snapshot of runtime linker rendezvous and recompute
@@ -100,6 +110,10 @@ public:
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
@@ -128,6 +142,7 @@ public:
/// 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.
@@ -142,6 +157,7 @@ public:
}
void clear() {
+ link_addr = 0;
base_addr = 0;
path_addr = 0;
dyn_addr = 0;
@@ -194,12 +210,22 @@ protected:
/// Resolve().
SOEntryList m_removed_soentries;
- /// Reads @p size bytes from the inferiors address space starting at @p
- /// addr.
+ /// 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
- ReadMemory(lldb::addr_t addr, void *dst, size_t size);
+ 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.
@@ -225,6 +251,10 @@ protected:
/// 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
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 91c7cd3dfca7..4284558c4409 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -123,7 +123,7 @@ DynamicLoaderPOSIXDYLD::DidAttach()
{
ModuleList module_list;
module_list.Append(executable);
- UpdateLoadedSections(executable, load_offset);
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
LoadAllCurrentModules();
m_process->GetTarget().ModulesDidLoad(module_list);
}
@@ -144,7 +144,7 @@ DynamicLoaderPOSIXDYLD::DidLaunch()
{
ModuleList module_list;
module_list.Append(executable);
- UpdateLoadedSections(executable, load_offset);
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
ProbeEntry();
m_process->GetTarget().ModulesDidLoad(module_list);
}
@@ -209,11 +209,15 @@ DynamicLoaderPOSIXDYLD::CanLoadImage()
}
void
-DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
+DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
{
- ObjectFile *obj_file = module->GetObjectFile();
- SectionList *sections = obj_file->GetSectionList();
SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
+ 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)
@@ -234,6 +238,24 @@ DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
}
void
+DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module)
+{
+ SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
+ 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));
+ load_list.SetSectionUnloaded(section_sp);
+ }
+}
+
+void
DynamicLoaderPOSIXDYLD::ProbeEntry()
{
Breakpoint *entry_break;
@@ -242,7 +264,7 @@ DynamicLoaderPOSIXDYLD::ProbeEntry()
if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
return;
- entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get();
+ entry_break = m_process->GetTarget().CreateBreakpoint(entry, true, false).get();
entry_break->SetCallback(EntryBreakpointHit, this, true);
entry_break->SetBreakpointKind("shared-library-event");
}
@@ -275,7 +297,7 @@ DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint()
if (m_dyld_bid == LLDB_INVALID_BREAK_ID)
{
- Breakpoint *dyld_break = target.CreateBreakpoint (break_addr, true).get();
+ 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();
@@ -319,10 +341,14 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
for (I = m_rendezvous.loaded_begin(); I != E; ++I)
{
FileSpec file(I->path.c_str(), true);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+ 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);
+ }
}
+ m_process->GetTarget().ModulesDidLoad(new_modules);
}
if (m_rendezvous.ModulesDidUnload())
@@ -336,10 +362,15 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
ModuleSpec module_spec (file);
ModuleSP module_sp =
loaded_modules.FindFirstModule (module_spec);
+
if (module_sp.get())
+ {
old_modules.Append(module_sp);
+ UnloadSections(module_sp);
+ }
}
loaded_modules.Remove(old_modules);
+ m_process->GetTarget().ModulesDidUnload(old_modules, false);
}
}
@@ -404,21 +435,43 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()
ModuleList module_list;
if (!m_rendezvous.Resolve())
+ {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (log)
+ log->Printf("DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD 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)
{
- FileSpec file(I->path.c_str(), false);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+ 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("DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64,
+ __FUNCTION__, module_path, I->base_addr);
+ }
}
m_process->GetTarget().ModulesDidLoad(module_list);
}
ModuleSP
-DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr)
+DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr)
{
Target &target = m_process->GetTarget();
ModuleList &modules = target.GetImages();
@@ -427,11 +480,11 @@ DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_ad
ModuleSpec module_spec (file, target.GetArchitecture());
if ((module_sp = modules.FindFirstModule (module_spec)))
{
- UpdateLoadedSections(module_sp, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr);
}
else if ((module_sp = target.GetSharedModule(module_spec)))
{
- UpdateLoadedSections(module_sp, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr);
}
return module_sp;
@@ -479,3 +532,83 @@ DynamicLoaderPOSIXDYLD::GetEntryPoint()
m_entry_point = static_cast<addr_t>(I->value);
return m_entry_point;
}
+
+const SectionList *
+DynamicLoaderPOSIXDYLD::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;
+}
+
+static addr_t ReadPointer(Process *process, addr_t addr)
+{
+ Error error;
+ addr_t value = process->ReadPointerFromMemory(addr, error);
+ if (error.Fail())
+ return LLDB_INVALID_ADDRESS;
+ else
+ return value;
+}
+
+lldb::addr_t
+DynamicLoaderPOSIXDYLD::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 DYLDRendezvous::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 (m_process, 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 (m_process, dtv_slot + metadata.tls_offset);
+
+ Module *mod = module.get();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (log)
+ log->Printf("DynamicLoaderPOSIXDYLD::Performed TLS lookup: "
+ "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%i, tls_block=0x%" PRIx64 "\n",
+ mod->GetObjectName().AsCString(""), link_map, tp, modid, tls_block);
+
+ return tls_block;
+}
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
index 0476e45d0465..7997b34195a4 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -61,6 +61,9 @@ public:
virtual lldb_private::Error
CanLoadImage();
+ virtual lldb::addr_t
+ GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread);
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -95,6 +98,9 @@ protected:
/// 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.
void
@@ -117,15 +123,24 @@ protected:
///
/// @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 base_addr = 0);
+ 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 base_addr);
+ LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr);
/// Resolves the entry point for the current inferior process and sets a
/// breakpoint at that address.
@@ -165,6 +180,9 @@ protected:
private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);
+
+ const lldb_private::SectionList *
+ GetSectionListFromModule(const lldb::ModuleSP module) const;
};
#endif // liblldb_DynamicLoaderPOSIXDYLD_H_
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 2dd04dd8733d..db03f4536188 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -196,7 +196,7 @@ EmulateInstructionARM::GetPluginDescriptionStatic ()
EmulateInstruction *
EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
{
- if (EmulateInstructionARM::SupportsEmulatingIntructionsOfTypeStatic(inst_type))
+ if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(inst_type))
{
if (arch.GetTriple().getArch() == llvm::Triple::arm)
{
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index b926dc0deb4a..a3c294ae7a05 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -79,7 +79,7 @@ public:
InstructionType inst_type);
static bool
- SupportsEmulatingIntructionsOfTypeStatic (InstructionType inst_type)
+ SupportsEmulatingInstructionsOfTypeStatic (InstructionType inst_type)
{
switch (inst_type)
{
@@ -149,9 +149,9 @@ public:
// }
virtual bool
- SupportsEmulatingIntructionsOfType (InstructionType inst_type)
+ SupportsEmulatingInstructionsOfType (InstructionType inst_type)
{
- return SupportsEmulatingIntructionsOfTypeStatic (inst_type);
+ return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
}
virtual bool
diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.h b/source/Plugins/Instruction/ARM/EmulationStateARM.h
index 8d84abc75614..ad596a3c2779 100644
--- a/source/Plugins/Instruction/ARM/EmulationStateARM.h
+++ b/source/Plugins/Instruction/ARM/EmulationStateARM.h
@@ -80,7 +80,7 @@ public:
const lldb_private::RegisterValue &reg_value);
private:
uint32_t m_gpr[17];
- struct sd_regs
+ struct _sd_regs
{
union
{
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 247d7b0e7fe4..d18b4c75ae7b 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -402,7 +402,7 @@ ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp,
FileSpecList filter_modules;
BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
SearchFilterSP filter_sp (CreateExceptionSearchFilter ());
- return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal);
+ return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, false);
}
void
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
index 1ec5f3d733a0..32574e3ef2f0 100644
--- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -9,7 +9,24 @@
#include "ObjectContainerBSDArchive.h"
+#ifdef _WIN32
+// Defines from ar, missing on Windows
+#define ARMAG "!<arch>\n"
+#define SARMAG 8
+#define ARFMAG "`\n"
+
+typedef struct ar_hdr
+{
+ char ar_name[16];
+ char ar_date[12];
+ char ar_uid[6], ar_gid[6];
+ char ar_mode[8];
+ char ar_size[10];
+ char ar_fmag[2];
+} ar_hdr;
+#else
#include <ar.h>
+#endif
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataBuffer.h"
@@ -444,7 +461,7 @@ ObjectContainerBSDArchive::Dump (Stream *s) const
s->Indent();
const size_t num_archs = GetNumArchitectures();
const size_t num_objects = GetNumObjects();
- s->Printf("ObjectContainerBSDArchive, num_archs = %lu, num_objects = %lu", num_archs, num_objects);
+ s->Printf("ObjectContainerBSDArchive, num_archs = %zu, num_objects = %zu", num_archs, num_objects);
uint32_t i;
ArchSpec arch;
s->IndentMore();
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 2e9f6903280c..163e713bedb2 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -21,7 +21,9 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Target.h"
#include "lldb/Host/Host.h"
#include "llvm/ADT/PointerUnion.h"
@@ -514,7 +516,7 @@ ObjectFileELF::GetDependentModules(FileSpecList &files)
}
Address
-ObjectFileELF::GetImageInfoAddress()
+ObjectFileELF::GetImageInfoAddress(Target *target)
{
if (!ParseDynamicSymbols())
return Address();
@@ -545,6 +547,17 @@ ObjectFileELF::GetImageInfoAddress()
addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
return Address(dynsym_section_sp, offset);
}
+ else if (symbol.d_tag == DT_MIPS_RLD_MAP && target)
+ {
+ addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
+ addr_t dyn_base = dynsym_section_sp->GetLoadBaseAddress(target);
+ if (dyn_base == LLDB_INVALID_ADDRESS)
+ return Address();
+ Address addr;
+ Error error;
+ if (target->ReadPointerFromMemory(dyn_base + offset, false, error, addr))
+ return addr;
+ }
}
return Address();
@@ -1280,6 +1293,11 @@ ObjectFileELF::FindDynamicSymbol(unsigned tag)
unsigned
ObjectFileELF::PLTRelocationType()
{
+ // DT_PLTREL
+ // This member specifies the type of relocation entry to which the
+ // procedure linkage table refers. The d_val member holds DT_REL or
+ // DT_RELA, as appropriate. All relocations in a procedure linkage table
+ // must use the same relocation.
const ELFDynamic *symbol = FindDynamicSymbol(DT_PLTREL);
if (symbol)
@@ -1304,7 +1322,10 @@ ParsePLTRelocations(Symtab *symbol_table,
ELFRelocation rel(rel_type);
ELFSymbol symbol;
lldb::offset_t offset = 0;
- const elf_xword plt_entsize = plt_hdr->sh_entsize;
+ // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16 bytes.
+ // So round the entsize up by the alignment if addralign is set.
+ const elf_xword plt_entsize = plt_hdr->sh_addralign ?
+ llvm::RoundUpToAlignment (plt_hdr->sh_entsize, plt_hdr->sh_addralign) : plt_hdr->sh_entsize;
const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
@@ -1479,10 +1500,17 @@ ObjectFileELF::GetSymtab()
if (symtab)
symbol_id += ParseSymbolTable (m_symtab_ap.get(), symbol_id, symtab);
- // Synthesize trampoline symbols to help navigate the PLT.
+ // DT_JMPREL
+ // If present, this entry's d_ptr member holds the address of relocation
+ // entries associated solely with the procedure linkage table. Separating
+ // these relocation entries lets the dynamic linker ignore them during
+ // process initialization, if lazy binding is enabled. If this entry is
+ // present, the related entries of types DT_PLTRELSZ and DT_PLTREL must
+ // also be present.
const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL);
if (symbol)
{
+ // Synthesize trampoline symbols to help navigate the PLT.
addr_t addr = symbol->d_ptr;
Section *reloc_section = section_list->FindSectionContainingFileAddress(addr).get();
if (reloc_section)
@@ -1498,6 +1526,57 @@ ObjectFileELF::GetSymtab()
return m_symtab_ap.get();
}
+Symbol *
+ObjectFileELF::ResolveSymbolForAddress(const Address& so_addr, bool verify_unique)
+{
+ if (!m_symtab_ap.get())
+ return nullptr; // GetSymtab() should be called first.
+
+ const SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return nullptr;
+
+ if (DWARFCallFrameInfo *eh_frame = GetUnwindTable().GetEHFrameInfo())
+ {
+ AddressRange range;
+ if (eh_frame->GetAddressRange (so_addr, range))
+ {
+ const addr_t file_addr = range.GetBaseAddress().GetFileAddress();
+ Symbol * symbol = verify_unique ? m_symtab_ap->FindSymbolContainingFileAddress(file_addr) : nullptr;
+ if (symbol)
+ return symbol;
+
+ // Note that a (stripped) symbol won't be found by GetSymtab()...
+ lldb::SectionSP eh_sym_section_sp = section_list->FindSectionContainingFileAddress(file_addr);
+ if (eh_sym_section_sp.get())
+ {
+ addr_t section_base = eh_sym_section_sp->GetFileAddress();
+ addr_t offset = file_addr - section_base;
+ uint64_t symbol_id = m_symtab_ap->GetNumSymbols();
+
+ Symbol eh_symbol(
+ symbol_id, // Symbol table index.
+ "???", // Symbol name.
+ false, // Is the symbol name mangled?
+ eSymbolTypeCode, // Type of this symbol.
+ true, // Is this globally visible?
+ false, // Is this symbol debug info?
+ false, // Is this symbol a trampoline?
+ true, // Is this symbol artificial?
+ eh_sym_section_sp, // Section in which this symbol is defined or null.
+ offset, // Offset in section or symbol value.
+ range.GetByteSize(), // Size in bytes of this symbol.
+ true, // Size is valid.
+ 0); // Symbol flags.
+ if (symbol_id == m_symtab_ap->AddSymbol(eh_symbol))
+ return m_symtab_ap->SymbolAtIndex(symbol_id);
+ }
+ }
+ }
+ return nullptr;
+}
+
+
bool
ObjectFileELF::IsStripped ()
{
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 2365101f4275..ede886fb4f60 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -102,6 +102,9 @@ public:
virtual lldb_private::Symtab *
GetSymtab();
+ virtual lldb_private::Symbol *
+ ResolveSymbolForAddress(const lldb_private::Address& so_addr, bool verify_unique);
+
virtual bool
IsStripped ();
@@ -124,7 +127,7 @@ public:
GetDependentModules(lldb_private::FileSpecList& files);
virtual lldb_private::Address
- GetImageInfoAddress();
+ GetImageInfoAddress(lldb_private::Target *target);
virtual lldb_private::Address
GetEntryPointAddress ();
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index 4cfe38e5840f..37b324197350 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -144,7 +144,7 @@ OperatingSystemPython::GetDynamicRegisterInfo ()
if (!dictionary)
return NULL;
- m_register_info_ap.reset (new DynamicRegisterInfo (dictionary));
+ m_register_info_ap.reset (new DynamicRegisterInfo (dictionary, m_process->GetTarget().GetArchitecture().GetByteOrder()));
assert (m_register_info_ap->GetNumRegisters() > 0);
assert (m_register_info_ap->GetNumRegisterSets() > 0);
}
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index dc0917255d9b..da29c16ac3ab 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -10,10 +10,13 @@
#include "lldb/lldb-python.h"
#include "PlatformFreeBSD.h"
+#include "lldb/Host/Config.h"
// C Includes
#include <stdio.h>
+#ifndef LLDB_DISABLE_POSIX
#include <sys/utsname.h>
+#endif
// C++ Includes
// Other libraries and framework includes
@@ -153,6 +156,26 @@ PlatformFreeBSD::~PlatformFreeBSD()
{
}
+//TODO:VK: inherit PlatformPOSIX
+lldb_private::Error
+PlatformFreeBSD::RunShellCommand (const char *command,
+ const char *working_dir,
+ int *status_ptr,
+ int *signo_ptr,
+ std::string *command_output,
+ uint32_t timeout_sec)
+{
+ if (IsHost())
+ return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ return Error("unable to run a remote command without a platform");
+ }
+}
+
Error
PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
@@ -162,10 +185,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
@@ -175,10 +198,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
@@ -214,7 +237,6 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
}
}
-
if (error.Success())
{
ModuleSpec module_spec (resolved_exe_file, exe_arch);
@@ -225,7 +247,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();
@@ -256,12 +278,12 @@ 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",
@@ -271,11 +293,6 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
}
}
}
- else
- {
- error.SetErrorStringWithFormat ("'%s' does not exist",
- exe_file.GetPath().c_str());
- }
return error;
}
@@ -636,13 +653,23 @@ PlatformFreeBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
void
PlatformFreeBSD::GetStatus (Stream &strm)
{
+#ifndef LLDB_DISABLE_POSIX
struct utsname un;
- if (uname(&un)) {
- strm << "FreeBSD";
- return;
- }
+ strm << " Host: ";
+
+ ::memset(&un, 0, sizeof(utsname));
+ if (uname(&un) == -1)
+ strm << "FreeBSD" << '\n';
+ strm << un.sysname << ' ' << un.release;
+ if (un.nodename[0] != '\0')
+ strm << " (" << un.nodename << ')';
+ strm << '\n';
+
+ // Dump a common information about the platform status.
strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
+#endif
+
Platform::GetStatus(strm);
}
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
index 4aa158eb6e87..11d1cd609779 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
@@ -72,6 +72,14 @@ public:
// lldb_private::Platform functions
//------------------------------------------------------------
virtual lldb_private::Error
+ RunShellCommand (const char *command,
+ const char *working_dir,
+ int *status_ptr,
+ int *signo_ptr,
+ std::string *command_output,
+ uint32_t timeout_sec);
+
+ virtual lldb_private::Error
ResolveExecutable (const lldb_private::FileSpec &exe_file,
const lldb_private::ArchSpec &arch,
lldb::ModuleSP &module_sp,
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
new file mode 100644
index 000000000000..34316c484276
--- /dev/null
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -0,0 +1,541 @@
+//===-- PlatformPOSIX.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformPOSIX.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/File.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformPOSIX::PlatformPOSIX (bool is_host) :
+Platform(is_host), // This is the local host platform
+m_remote_platform_sp ()
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformPOSIX::~PlatformPOSIX()
+{
+}
+
+lldb_private::OptionGroupOptions*
+PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpreter)
+{
+ if (m_options.get() == NULL)
+ {
+ m_options.reset(new OptionGroupOptions(interpreter));
+ m_options->Append(new OptionGroupPlatformRSync());
+ m_options->Append(new OptionGroupPlatformSSH());
+ m_options->Append(new OptionGroupPlatformCaching());
+ }
+ return m_options.get();
+}
+
+lldb_private::Error
+PlatformPOSIX::RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish
+{
+ if (IsHost())
+ return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ return Error("unable to run a remote command without a platform");
+ }
+}
+
+uint32_t
+PlatformPOSIX::MakeDirectory (const std::string &path,
+ mode_t mode)
+{
+ if (IsHost())
+ {
+ return Host::MakeDirectory (path.c_str(), mode);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->MakeDirectory(path, mode);
+ return Platform::MakeDirectory(path,mode);
+}
+
+lldb::user_id_t
+PlatformPOSIX::OpenFile (const FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ Error &error)
+{
+ if (IsHost())
+ {
+ return Host::OpenFile(file_spec, flags, mode, error);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error);
+ return Platform::OpenFile(file_spec, flags, mode, error);
+}
+
+bool
+PlatformPOSIX::CloseFile (lldb::user_id_t fd, Error &error)
+{
+ if (IsHost())
+ {
+ return Host::CloseFile(fd, error);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->CloseFile(fd, error);
+ return Platform::CloseFile(fd, error);
+}
+
+uint64_t
+PlatformPOSIX::ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ Error &error)
+{
+ if (IsHost())
+ {
+ return Host::ReadFile(fd, offset, dst, dst_len, error);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error);
+ return Platform::ReadFile(fd, offset, dst, dst_len, error);
+}
+
+uint64_t
+PlatformPOSIX::WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ Error &error)
+{
+ if (IsHost())
+ {
+ return Host::WriteFile(fd, offset, src, src_len, error);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error);
+
+ return Platform::WriteFile(fd, offset, src, src_len, error);
+}
+
+static uint32_t
+chown_file(Platform *platform,
+ const char* path,
+ uint32_t uid = UINT32_MAX,
+ uint32_t gid = UINT32_MAX)
+{
+ if (!platform || !path || *path == 0)
+ return UINT32_MAX;
+
+ if (uid == UINT32_MAX && gid == UINT32_MAX)
+ return 0; // pretend I did chown correctly - actually I just didn't care
+
+ StreamString command;
+ command.PutCString("chown ");
+ if (uid != UINT32_MAX)
+ command.Printf("%d",uid);
+ if (gid != UINT32_MAX)
+ command.Printf(":%d",gid);
+ command.Printf("%s",path);
+ int status;
+ platform->RunShellCommand(command.GetData(),
+ NULL,
+ &status,
+ NULL,
+ NULL,
+ 10);
+ return status;
+}
+
+lldb_private::Error
+PlatformPOSIX::PutFile (const lldb_private::FileSpec& source,
+ const lldb_private::FileSpec& destination,
+ uint32_t uid,
+ uint32_t gid)
+{
+ if (IsHost())
+ {
+ if (FileSpec::Equal(source, destination, true))
+ return Error();
+ // cp src dst
+ // chown uid:gid dst
+ std::string src_path (source.GetPath());
+ if (src_path.empty())
+ return Error("unable to get file path for source");
+ std::string dst_path (destination.GetPath());
+ if (dst_path.empty())
+ return Error("unable to get file path for destination");
+ StreamString command;
+ command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
+ int status;
+ RunShellCommand(command.GetData(),
+ NULL,
+ &status,
+ NULL,
+ NULL,
+ 10);
+ if (status != 0)
+ return Error("unable to perform copy");
+ if (uid == UINT32_MAX && gid == UINT32_MAX)
+ return Error();
+ if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
+ return Error("unable to perform chown");
+ return Error();
+ }
+ else if (IsRemote() && m_remote_platform_sp)
+ {
+ if (GetSupportsRSync())
+ {
+ std::string src_path (source.GetPath());
+ if (src_path.empty())
+ return Error("unable to get file path for source");
+ std::string dst_path (destination.GetPath());
+ if (dst_path.empty())
+ return Error("unable to get file path for destination");
+ StreamString command;
+ if (GetIgnoresRemoteHostname())
+ {
+ if (!GetRSyncPrefix())
+ command.Printf("rsync %s %s %s",
+ GetRSyncOpts(),
+ src_path.c_str(),
+ dst_path.c_str());
+ else
+ command.Printf("rsync %s %s %s%s",
+ GetRSyncOpts(),
+ src_path.c_str(),
+ GetRSyncPrefix(),
+ dst_path.c_str());
+ }
+ else
+ command.Printf("rsync %s %s %s:%s",
+ GetRSyncOpts(),
+ src_path.c_str(),
+ GetHostname(),
+ dst_path.c_str());
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[PutFile] Running command: %s\n", command.GetData());
+ int retcode;
+ Host::RunShellCommand(command.GetData(),
+ NULL,
+ &retcode,
+ NULL,
+ NULL,
+ 60);
+ if (retcode == 0)
+ {
+ // Don't chown a local file for a remote system
+// if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
+// return Error("unable to perform chown");
+ return Error();
+ }
+ // if we are still here rsync has failed - let's try the slow way before giving up
+ }
+ // open
+ // read, write, read, write, ...
+ // close
+ // chown uid:gid dst
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[PutFile] Using block by block transfer....\n");
+ File source_file(source, File::eOpenOptionRead, File::ePermissionsUserRW);
+ if (!source_file.IsValid())
+ return Error("unable to open source file");
+ Error error;
+ lldb::user_id_t dest_file = OpenFile (destination,
+ File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
+ File::ePermissionsUserRWX | File::ePermissionsGroupRX | File::ePermissionsWorldRX,
+ error);
+ if (log)
+ log->Printf ("dest_file = %" PRIu64 "\n", dest_file);
+ if (error.Fail())
+ return error;
+ if (dest_file == UINT64_MAX)
+ return Error("unable to open target file");
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+ uint64_t offset = 0;
+ while (error.Success())
+ {
+ size_t bytes_read = buffer_sp->GetByteSize();
+ error = source_file.Read(buffer_sp->GetBytes(), bytes_read);
+ if (bytes_read)
+ {
+ WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error);
+ offset += bytes_read;
+ }
+ else
+ break;
+ }
+ CloseFile(dest_file, error);
+ if (uid == UINT32_MAX && gid == UINT32_MAX)
+ return error;
+ // This is remopve, don't chown a local file...
+// std::string dst_path (destination.GetPath());
+// if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
+// return Error("unable to perform chown");
+ return error;
+ }
+ return Platform::PutFile(source,destination,uid,gid);
+}
+
+lldb::user_id_t
+PlatformPOSIX::GetFileSize (const FileSpec& file_spec)
+{
+ if (IsHost())
+ {
+ return Host::GetFileSize(file_spec);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetFileSize(file_spec);
+ return Platform::GetFileSize(file_spec);
+}
+
+bool
+PlatformPOSIX::GetFileExists (const FileSpec& file_spec)
+{
+ if (IsHost())
+ {
+ return file_spec.Exists();
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetFileExists(file_spec);
+ return Platform::GetFileExists(file_spec);
+}
+
+uint32_t
+PlatformPOSIX::GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ lldb_private::Error &error)
+{
+ if (IsHost())
+ {
+ return File::GetPermissions(file_spec.GetPath().c_str(), error);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetFilePermissions(file_spec, error);
+ return Platform::GetFilePermissions(file_spec, error);
+
+}
+
+
+lldb_private::Error
+PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path */,
+ const lldb_private::FileSpec& destination /* local file path */)
+{
+ // Check the args, first.
+ std::string src_path (source.GetPath());
+ if (src_path.empty())
+ return Error("unable to get file path for source");
+ std::string dst_path (destination.GetPath());
+ if (dst_path.empty())
+ return Error("unable to get file path for destination");
+ if (IsHost())
+ {
+ if (FileSpec::Equal(source, destination, true))
+ return Error("local scenario->source and destination are the same file path: no operation performed");
+ // cp src dst
+ StreamString cp_command;
+ cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
+ int status;
+ RunShellCommand(cp_command.GetData(),
+ NULL,
+ &status,
+ NULL,
+ NULL,
+ 10);
+ if (status != 0)
+ return Error("unable to perform copy");
+ return Error();
+ }
+ else if (IsRemote() && m_remote_platform_sp)
+ {
+ if (GetSupportsRSync())
+ {
+ StreamString command;
+ if (GetIgnoresRemoteHostname())
+ {
+ if (!GetRSyncPrefix())
+ command.Printf("rsync %s %s %s",
+ GetRSyncOpts(),
+ src_path.c_str(),
+ dst_path.c_str());
+ else
+ command.Printf("rsync %s %s%s %s",
+ GetRSyncOpts(),
+ GetRSyncPrefix(),
+ src_path.c_str(),
+ dst_path.c_str());
+ }
+ else
+ command.Printf("rsync %s %s:%s %s",
+ GetRSyncOpts(),
+ m_remote_platform_sp->GetHostname(),
+ src_path.c_str(),
+ dst_path.c_str());
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[GetFile] Running command: %s\n", command.GetData());
+ int retcode;
+ Host::RunShellCommand(command.GetData(),
+ NULL,
+ &retcode,
+ NULL,
+ NULL,
+ 60);
+ if (retcode == 0)
+ return Error();
+ // If we are here, rsync has failed - let's try the slow way before giving up
+ }
+ // open src and dst
+ // read/write, read/write, read/write, ...
+ // close src
+ // close dst
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[GetFile] Using block by block transfer....\n");
+ Error error;
+ user_id_t fd_src = OpenFile (source,
+ File::eOpenOptionRead,
+ File::ePermissionsDefault,
+ error);
+
+ if (fd_src == UINT64_MAX)
+ return Error("unable to open source file");
+
+ uint32_t permissions = GetFilePermissions(source, error);
+
+ if (permissions == 0)
+ permissions = File::ePermissionsDefault;
+
+ user_id_t fd_dst = Host::OpenFile(destination,
+ File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
+ permissions,
+ error);
+
+ if (fd_dst == UINT64_MAX)
+ {
+ if (error.Success())
+ error.SetErrorString("unable to open destination file");
+ }
+
+ if (error.Success())
+ {
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+ uint64_t offset = 0;
+ error.Clear();
+ while (error.Success())
+ {
+ const uint64_t n_read = ReadFile (fd_src,
+ offset,
+ buffer_sp->GetBytes(),
+ buffer_sp->GetByteSize(),
+ error);
+ if (error.Fail())
+ break;
+ if (n_read == 0)
+ break;
+ if (Host::WriteFile(fd_dst,
+ offset,
+ buffer_sp->GetBytes(),
+ n_read,
+ error) != n_read)
+ {
+ if (!error.Fail())
+ error.SetErrorString("unable to write to destination file");
+ break;
+ }
+ offset += n_read;
+ }
+ }
+ // Ignore the close error of src.
+ 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 (!error.Fail())
+ error.SetErrorString("unable to close destination file");
+
+ }
+ return error;
+ }
+ return Platform::GetFile(source,destination);
+}
+
+std::string
+PlatformPOSIX::GetPlatformSpecificConnectionInformation()
+{
+ StreamString stream;
+ if (GetSupportsRSync())
+ {
+ stream.PutCString("rsync");
+ if ( (GetRSyncOpts() && *GetRSyncOpts()) ||
+ (GetRSyncPrefix() && *GetRSyncPrefix()) ||
+ GetIgnoresRemoteHostname())
+ {
+ stream.Printf(", options: ");
+ if (GetRSyncOpts() && *GetRSyncOpts())
+ stream.Printf("'%s' ",GetRSyncOpts());
+ stream.Printf(", prefix: ");
+ if (GetRSyncPrefix() && *GetRSyncPrefix())
+ stream.Printf("'%s' ",GetRSyncPrefix());
+ if (GetIgnoresRemoteHostname())
+ stream.Printf("ignore remote-hostname ");
+ }
+ }
+ if (GetSupportsSSH())
+ {
+ stream.PutCString("ssh");
+ if (GetSSHOpts() && *GetSSHOpts())
+ stream.Printf(", options: '%s' ",GetSSHOpts());
+ }
+ if (GetLocalCacheDirectory() && *GetLocalCacheDirectory())
+ stream.Printf("cache dir: %s",GetLocalCacheDirectory());
+ if (stream.GetSize())
+ return stream.GetData();
+ else
+ return "";
+}
+
+bool
+PlatformPOSIX::CalculateMD5 (const FileSpec& file_spec,
+ uint64_t &low,
+ uint64_t &high)
+{
+ if (IsHost())
+ return Platform::CalculateMD5 (file_spec, low, high);
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->CalculateMD5(file_spec, low, high);
+ return false;
+}
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
new file mode 100644
index 000000000000..4119e452bf7f
--- /dev/null
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -0,0 +1,111 @@
+//===-- PlatformPOSIX.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_PlatformPOSIX_h_
+#define liblldb_PlatformPOSIX_h_
+
+// C Includes
+// C++ Includes
+
+#include <memory>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/Options.h"
+#include "lldb/Target/Platform.h"
+
+class PlatformPOSIX : public lldb_private::Platform
+{
+public:
+ PlatformPOSIX (bool is_host);
+
+ virtual
+ ~PlatformPOSIX();
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+ virtual lldb_private::OptionGroupOptions*
+ GetConnectionOptions (lldb_private::CommandInterpreter& interpreter);
+
+ virtual lldb_private::Error
+ PutFile (const lldb_private::FileSpec& source,
+ const lldb_private::FileSpec& destination,
+ uint32_t uid = UINT32_MAX,
+ uint32_t gid = UINT32_MAX);
+
+ virtual lldb::user_id_t
+ OpenFile (const lldb_private::FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ lldb_private::Error &error);
+
+ virtual bool
+ CloseFile (lldb::user_id_t fd,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ lldb_private::Error &error);
+
+ virtual lldb::user_id_t
+ GetFileSize (const lldb_private::FileSpec& file_spec);
+
+ virtual lldb_private::Error
+ GetFile (const lldb_private::FileSpec& source,
+ const lldb_private::FileSpec& destination);
+
+ virtual lldb_private::Error
+ RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
+
+ virtual uint32_t
+ MakeDirectory (const std::string &path,
+ mode_t mode);
+
+ virtual bool
+ GetFileExists (const lldb_private::FileSpec& file_spec);
+
+ virtual uint32_t
+ GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ lldb_private::Error &error);
+
+ virtual std::string
+ GetPlatformSpecificConnectionInformation();
+
+ virtual bool
+ CalculateMD5 (const lldb_private::FileSpec& file_spec,
+ uint64_t &low,
+ uint64_t &high);
+
+protected:
+ std::auto_ptr<lldb_private::OptionGroupOptions> m_options;
+
+ lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote POSIX-compliant OS
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformPOSIX);
+
+};
+
+#endif // liblldb_PlatformPOSIX_h_
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 684d1921e920..4aeec032d712 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -10,9 +10,12 @@
#include "lldb/lldb-python.h"
#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
@@ -107,7 +110,11 @@ PlatformRemoteGDBServer::ResolveExecutable (const FileSpec &exe_file,
const FileSpecList *module_search_paths_ptr)
{
Error error;
- error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented");
+ //error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented");
+ if (m_gdb_client.GetFileExists(exe_file))
+ return error;
+ // TODO: get the remote end to somehow resolve this file
+ error.SetErrorString("file not found on remote end");
return error;
}
@@ -230,6 +237,11 @@ PlatformRemoteGDBServer::ConnectRemote (Args& args)
error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
}
}
+
+ if (error.Success())
+ {
+
+ }
return error;
}
@@ -324,6 +336,12 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
break;
}
}
+
+ ArchSpec arch_spec = launch_info.GetArchitecture();
+ const char *arch_triple = arch_spec.GetTriple().str().c_str();
+
+ m_gdb_client.SendLaunchArchPacket(arch_triple);
+
const uint32_t old_packet_timeout = m_gdb_client.SetPacketTimeout (5);
int arg_packet_err = m_gdb_client.SendArgumentsPacket (argv);
m_gdb_client.SetPacketTimeout (old_packet_timeout);
@@ -360,7 +378,8 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
{
if (IsConnected())
{
- uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort();
+ lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid);
if (port == 0)
{
@@ -394,15 +413,22 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
if (process_sp)
{
char connect_url[256];
+ const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
+ const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
+ int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;
const int connect_url_len = ::snprintf (connect_url,
sizeof(connect_url),
"connect://%s:%u",
- GetHostname (),
- port);
+ override_hostname ? override_hostname : GetHostname (),
+ port + port_offset);
assert (connect_url_len < (int)sizeof(connect_url));
error = process_sp->ConnectRemote (NULL, connect_url);
if (error.Success())
error = process_sp->Attach(attach_info);
+ else if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ {
+ m_gdb_client.KillSpawnedProcess(debugserver_pid);
+ }
}
}
}
@@ -415,4 +441,83 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
return process_sp;
}
+uint32_t
+PlatformRemoteGDBServer::MakeDirectory (const std::string &path,
+ mode_t mode)
+{
+ return m_gdb_client.MakeDirectory(path,mode);
+}
+
+lldb::user_id_t
+PlatformRemoteGDBServer::OpenFile (const lldb_private::FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ Error &error)
+{
+ return m_gdb_client.OpenFile (file_spec, flags, mode, error);
+}
+
+bool
+PlatformRemoteGDBServer::CloseFile (lldb::user_id_t fd, Error &error)
+{
+ return m_gdb_client.CloseFile (fd, error);
+}
+
+lldb::user_id_t
+PlatformRemoteGDBServer::GetFileSize (const lldb_private::FileSpec& file_spec)
+{
+ return m_gdb_client.GetFileSize(file_spec);
+}
+uint32_t
+PlatformRemoteGDBServer::GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ lldb_private::Error &error)
+{
+ return m_gdb_client.GetFilePermissions(file_spec, error);
+}
+
+uint64_t
+PlatformRemoteGDBServer::ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ Error &error)
+{
+ return m_gdb_client.ReadFile (fd, offset, dst, dst_len, error);
+}
+
+uint64_t
+PlatformRemoteGDBServer::WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ Error &error)
+{
+ return m_gdb_client.WriteFile (fd, offset, src, src_len, error);
+}
+
+lldb_private::Error
+PlatformRemoteGDBServer::PutFile (const lldb_private::FileSpec& source,
+ const lldb_private::FileSpec& destination,
+ uint32_t uid,
+ uint32_t gid)
+{
+ return Platform::PutFile(source,destination,uid,gid);
+}
+
+bool
+PlatformRemoteGDBServer::GetFileExists (const lldb_private::FileSpec& file_spec)
+{
+ return m_gdb_client.GetFileExists (file_spec);
+}
+
+lldb_private::Error
+PlatformRemoteGDBServer::RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish
+{
+ return m_gdb_client.RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+}
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index 22b3dd49be54..70db6bafacd2 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -134,6 +134,58 @@ public:
virtual lldb_private::Error
DisconnectRemote ();
+
+ virtual uint32_t
+ MakeDirectory (const std::string &path,
+ mode_t mode);
+
+ virtual lldb::user_id_t
+ OpenFile (const lldb_private::FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ lldb_private::Error &error);
+
+ virtual bool
+ CloseFile (lldb::user_id_t fd,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *data_ptr,
+ uint64_t len,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* data,
+ uint64_t len,
+ lldb_private::Error &error);
+
+ virtual lldb::user_id_t
+ GetFileSize (const lldb_private::FileSpec& file_spec);
+
+ virtual lldb_private::Error
+ PutFile (const lldb_private::FileSpec& source,
+ const lldb_private::FileSpec& destination,
+ uint32_t uid = UINT32_MAX,
+ uint32_t gid = UINT32_MAX);
+
+ virtual bool
+ GetFileExists (const lldb_private::FileSpec& file_spec);
+
+ virtual uint32_t
+ GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ lldb_private::Error &error);
+
+ virtual lldb_private::Error
+ RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
protected:
GDBRemoteCommunicationClient m_gdb_client;
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
index ea26d972b860..952ec95f5873 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
@@ -122,11 +122,47 @@ ProcessFreeBSD::Terminate()
{
}
+Error
+ProcessFreeBSD::DoDetach(bool keep_stopped)
+{
+ Error error;
+ if (keep_stopped)
+ {
+ error.SetErrorString("Detaching with keep_stopped true is not currently supported on FreeBSD.");
+ return error;
+ }
+
+ error = m_monitor->Detach(GetID());
+
+ if (error.Success())
+ SetPrivateState(eStateDetached);
+
+ return error;
+}
+
bool
ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
{
- // XXX haxx
- new_thread_list = old_thread_list;
-
- return false;
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIu64 ")", __FUNCTION__, GetID());
+
+ bool has_updated = false;
+ const lldb::pid_t pid = GetID();
+ // Update the process thread list with this new thread.
+ // FIXME: We should be using tid, not pid.
+ assert(m_monitor);
+ ThreadSP thread_sp (old_thread_list.FindThreadByID (pid, false));
+ if (!thread_sp) {
+ ProcessSP me = this->shared_from_this();
+ thread_sp.reset(new POSIXThread(*me, pid));
+ has_updated = true;
+ }
+
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessFreeBSD::%s() updated tid = %" PRIu64, __FUNCTION__, pid);
+
+ new_thread_list.AddThread(thread_sp);
+
+ return has_updated; // the list has been updated
}
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
index 5f79b74cad30..fb549745b80c 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
@@ -54,6 +54,9 @@ public:
ProcessFreeBSD(lldb_private::Target& target,
lldb_private::Listener &listener);
+ virtual lldb_private::Error
+ DoDetach(bool keep_stopped);
+
virtual bool
UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list);
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 9fd51d2d640a..3833fa6baf85 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -70,12 +70,12 @@ PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
if (log) {
- log->Printf("ptrace(%s, %lu, %p, %x) called from file %s line %d",
+ log->Printf("ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d",
reqName, pid, addr, data, file, line);
if (req == PT_IO) {
struct ptrace_io_desc *pi = (struct ptrace_io_desc *) addr;
- log->Printf("PT_IO: op=%s offs=%zx size=%ld",
+ log->Printf("PT_IO: op=%s offs=%zx size=%zu",
Get_PT_IO_OP(pi->piod_op), (size_t)pi->piod_offs, pi->piod_len);
}
}
@@ -704,23 +704,16 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
m_operation_thread(LLDB_INVALID_HOST_THREAD),
m_monitor_thread(LLDB_INVALID_HOST_THREAD),
m_pid(LLDB_INVALID_PROCESS_ID),
- m_server_mutex(Mutex::eMutexTypeRecursive),
m_terminal_fd(-1),
- m_client_fd(-1),
- m_server_fd(-1)
+ m_operation(0)
{
- std::unique_ptr<LaunchArgs> args;
-
- args.reset(new LaunchArgs(this, module, argv, envp,
- stdin_path, stdout_path, stderr_path, working_dir));
+ std::unique_ptr<LaunchArgs> args(new LaunchArgs(this, module, argv, envp,
+ stdin_path, stdout_path, stderr_path,
+ working_dir));
- // Server/client descriptors.
- if (!EnableIPC())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Monitor failed to initialize.");
- }
+ sem_init(&m_operation_pending, 0, 0);
+ sem_init(&m_operation_done, 0, 0);
StartLaunchOpThread(args.get(), error);
if (!error.Success())
@@ -765,21 +758,14 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
m_operation_thread(LLDB_INVALID_HOST_THREAD),
m_monitor_thread(LLDB_INVALID_HOST_THREAD),
m_pid(pid),
- m_server_mutex(Mutex::eMutexTypeRecursive),
m_terminal_fd(-1),
- m_client_fd(-1),
- m_server_fd(-1)
+ m_operation(0)
{
- std::unique_ptr<AttachArgs> args;
+ sem_init(&m_operation_pending, 0, 0);
+ sem_init(&m_operation_done, 0, 0);
- args.reset(new AttachArgs(this, pid));
- // Server/client descriptors.
- if (!EnableIPC())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Monitor failed to initialize.");
- }
+ std::unique_ptr<AttachArgs> args(new AttachArgs(this, pid));
StartAttachOpThread(args.get(), error);
if (!error.Success())
@@ -855,7 +841,6 @@ ProcessMonitor::Launch(LaunchArgs *args)
{
ProcessMonitor *monitor = args->m_monitor;
ProcessFreeBSD &process = monitor->GetProcess();
- lldb::ProcessSP processSP = process.shared_from_this();
const char **argv = args->m_argv;
const char **envp = args->m_envp;
const char *stdin_path = args->m_stdin_path;
@@ -868,21 +853,10 @@ ProcessMonitor::Launch(LaunchArgs *args)
char err_str[err_len];
lldb::pid_t pid;
- lldb::ThreadSP inferior;
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
-
// Propagate the environment if one is not supplied.
if (envp == NULL || envp[0] == NULL)
envp = const_cast<const char **>(environ);
- // Pseudo terminal setup.
- if (!terminal.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, err_str, err_len))
- {
- args->m_error.SetErrorToGenericError();
- args->m_error.SetErrorString("Could not open controlling TTY.");
- goto FINISH;
- }
-
if ((pid = terminal.Fork(err_str, err_len)) == -1)
{
args->m_error.SetErrorToGenericError();
@@ -1002,32 +976,12 @@ ProcessMonitor::Launch(LaunchArgs *args)
if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error))
goto FINISH;
- // Update the process thread list with this new thread.
- inferior.reset(process.CreateNewPOSIXThread(*processSP, pid));
- if (log)
- log->Printf ("ProcessMonitor::%s() adding pid = %" PRIu64, __FUNCTION__, pid);
- process.GetThreadList().AddThread(inferior);
-
- // Let our process instance know the thread has stopped.
- process.SendMessage(ProcessMessage::Trace(pid));
+ process.SendMessage(ProcessMessage::Attach(pid));
FINISH:
return args->m_error.Success();
}
-bool
-ProcessMonitor::EnableIPC()
-{
- int fd[2];
-
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd))
- return false;
-
- m_client_fd = fd[0];
- m_server_fd = fd[1];
- return true;
-}
-
void
ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error)
{
@@ -1059,9 +1013,6 @@ ProcessMonitor::Attach(AttachArgs *args)
ProcessMonitor *monitor = args->m_monitor;
ProcessFreeBSD &process = monitor->GetProcess();
- lldb::ProcessSP processSP = process.shared_from_this();
- ThreadList &tl = process.GetThreadList();
- lldb::ThreadSP inferior;
if (pid <= 1)
{
@@ -1084,14 +1035,9 @@ ProcessMonitor::Attach(AttachArgs *args)
goto FINISH;
}
- // Update the process thread list with the attached thread.
- inferior.reset(process.CreateNewPOSIXThread(*processSP, pid));
- tl.AddThread(inferior);
+ process.SendMessage(ProcessMessage::Attach(pid));
- // Let our process instance know the thread has stopped.
- process.SendMessage(ProcessMessage::Trace(pid));
-
- FINISH:
+FINISH:
return args->m_error.Success();
}
@@ -1393,78 +1339,37 @@ void
ProcessMonitor::ServeOperation(OperationArgs *args)
{
int status;
- pollfd fdset;
ProcessMonitor *monitor = args->m_monitor;
- fdset.fd = monitor->m_server_fd;
- fdset.events = POLLIN | POLLPRI;
- fdset.revents = 0;
-
// We are finised with the arguments and are ready to go. Sync with the
// parent thread and start serving operations on the inferior.
sem_post(&args->m_semaphore);
for (;;)
{
- if ((status = poll(&fdset, 1, -1)) < 0)
- {
- switch (errno)
- {
- default:
- assert(false && "Unexpected poll() failure!");
- continue;
+ // wait for next pending operation
+ sem_wait(&monitor->m_operation_pending);
- case EINTR: continue; // Just poll again.
- case EBADF: return; // Connection terminated.
- }
- }
-
- assert(status == 1 && "Too many descriptors!");
+ monitor->m_operation->Execute(monitor);
- if (fdset.revents & POLLIN)
- {
- Operation *op = NULL;
-
- READ_AGAIN:
- if ((status = read(fdset.fd, &op, sizeof(op))) < 0)
- {
- // There is only one acceptable failure.
- assert(errno == EINTR);
- goto READ_AGAIN;
- }
- if (status == 0)
- continue; // Poll again. The connection probably terminated.
- assert(status == sizeof(op));
- op->Execute(monitor);
- write(fdset.fd, &op, sizeof(op));
- }
+ // notify calling thread that operation is complete
+ sem_post(&monitor->m_operation_done);
}
}
void
ProcessMonitor::DoOperation(Operation *op)
{
- int status;
- Operation *ack = NULL;
- Mutex::Locker lock(m_server_mutex);
+ Mutex::Locker lock(m_operation_mutex);
- // FIXME: Do proper error checking here.
- write(m_client_fd, &op, sizeof(op));
+ m_operation = op;
-READ_AGAIN:
- if ((status = read(m_client_fd, &ack, sizeof(ack))) < 0)
- {
- // If interrupted by a signal handler try again. Otherwise the monitor
- // thread probably died and we have a stale file descriptor -- abort the
- // operation.
- if (errno == EINTR)
- goto READ_AGAIN;
- return;
- }
+ // notify operation thread that an operation is ready to be processed
+ sem_post(&m_operation_pending);
- assert(status == sizeof(ack));
- assert(ack == op && "Invalid monitor thread response!");
+ // wait for operation to complete
+ sem_wait(&m_operation_done);
}
size_t
@@ -1556,6 +1461,12 @@ ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, un
}
bool
+ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value)
+{
+ return false;
+}
+
+bool
ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo)
{
bool result;
@@ -1648,9 +1559,36 @@ ProcessMonitor::StopMonitor()
{
StopMonitoringChildProcess();
StopOpThread();
- CloseFD(m_terminal_fd);
- CloseFD(m_client_fd);
- CloseFD(m_server_fd);
+ sem_destroy(&m_operation_pending);
+ sem_destroy(&m_operation_done);
+
+ // Note: ProcessPOSIX passes the m_terminal_fd file descriptor to
+ // Process::SetSTDIOFileDescriptor, which in turn transfers ownership of
+ // the descriptor to a ConnectionFileDescriptor object. Consequently
+ // even though still has the file descriptor, we shouldn't close it here.
+}
+
+// FIXME: On Linux, when a new thread is created, we receive to notifications,
+// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the
+// child thread id as additional information, and (2) a SIGSTOP|SI_USER from
+// the new child thread indicating that it has is stopped because we attached.
+// We have no guarantee of the order in which these arrive, but we need both
+// before we are ready to proceed. We currently keep a list of threads which
+// have sent the initial SIGSTOP|SI_USER event. Then when we receive the
+// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not occurred
+// we call ProcessMonitor::WaitForInitialTIDStop() to wait for it.
+//
+// Right now, the above logic is in ProcessPOSIX, so we need a definition of
+// this function in the FreeBSD ProcessMonitor implementation even if it isn't
+// logically needed.
+//
+// We really should figure out what actually happens on FreeBSD and move the
+// Linux-specific logic out of ProcessPOSIX as needed.
+
+bool
+ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid)
+{
+ return true;
}
void
@@ -1665,13 +1603,3 @@ ProcessMonitor::StopOpThread()
Host::ThreadJoin(m_operation_thread, &result, NULL);
m_operation_thread = LLDB_INVALID_HOST_THREAD;
}
-
-void
-ProcessMonitor::CloseFD(int &fd)
-{
- if (fd != -1)
- {
- close(fd);
- fd = -1;
- }
-}
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
index ce66c03f2f8c..4a9b48370444 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -160,6 +160,10 @@ public:
bool
WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
+ /// Reads the value of the thread-specific pointer for a given thread ID.
+ bool
+ ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value);
+
/// Writes a ptrace_lwpinfo structure corresponding to the given thread ID
/// to the memory region pointed to by @p lwpinfo.
bool
@@ -193,6 +197,10 @@ public:
void
StopMonitor();
+ // Waits for the initial stop message from a new thread.
+ bool
+ WaitForInitialTIDStop(lldb::tid_t tid);
+
private:
ProcessFreeBSD *m_process;
@@ -200,12 +208,17 @@ private:
lldb::thread_t m_monitor_thread;
lldb::pid_t m_pid;
-
- lldb_private::Mutex m_server_mutex;
int m_terminal_fd;
- int m_client_fd;
- int m_server_fd;
+ // current operation which must be executed on the privileged thread
+ Operation *m_operation;
+ lldb_private::Mutex m_operation_mutex;
+
+ // semaphores notified when Operation is ready to be processed and when
+ // the operation is complete.
+ sem_t m_operation_pending;
+ sem_t m_operation_done;
+
struct OperationArgs
{
OperationArgs(ProcessMonitor *monitor);
@@ -252,9 +265,6 @@ private:
static bool
Launch(LaunchArgs *args);
- bool
- EnableIPC();
-
struct AttachArgs : OperationArgs
{
AttachArgs(ProcessMonitor *monitor,
@@ -314,9 +324,6 @@ private:
/// Stops the operation thread used to attach/launch a process.
void
StopOpThread();
-
- void
- CloseFD(int &fd);
};
#endif // #ifndef liblldb_ProcessMonitor_H_
diff --git a/source/Plugins/Process/POSIX/POSIXThread.cpp b/source/Plugins/Process/POSIX/POSIXThread.cpp
index 93c296679df2..16399748c544 100644
--- a/source/Plugins/Process/POSIX/POSIXThread.cpp
+++ b/source/Plugins/Process/POSIX/POSIXThread.cpp
@@ -29,10 +29,12 @@
#include "ProcessPOSIX.h"
#include "ProcessPOSIXLog.h"
#include "ProcessMonitor.h"
-#include "RegisterContext_i386.h"
-#include "RegisterContext_x86_64.h"
-#include "RegisterContextPOSIX.h"
+#include "RegisterContextPOSIXProcessMonitor_mips64.h"
+#include "RegisterContextPOSIXProcessMonitor_x86.h"
+#include "RegisterContextLinux_i386.h"
#include "RegisterContextLinux_x86_64.h"
+#include "RegisterContextFreeBSD_i386.h"
+#include "RegisterContextFreeBSD_mips64.h"
#include "RegisterContextFreeBSD_x86_64.h"
#include "UnwindLLDB.h"
@@ -46,7 +48,8 @@ POSIXThread::POSIXThread(Process &process, lldb::tid_t tid)
m_frame_ap (),
m_breakpoint (),
m_thread_name_valid (false),
- m_thread_name ()
+ m_thread_name (),
+ m_posix_thread(NULL)
{
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
@@ -138,34 +141,66 @@ POSIXThread::GetRegisterContext()
{
if (!m_reg_context_sp)
{
- ArchSpec arch = Host::GetArchitecture();
+ m_posix_thread = NULL;
- switch (arch.GetCore())
+ RegisterInfoInterface *reg_interface = NULL;
+ const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture();
+
+ switch (target_arch.GetCore())
{
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- m_reg_context_sp.reset(new RegisterContext_i386(*this, 0));
- break;
-
- case ArchSpec::eCore_x86_64_x86_64:
- switch (arch.GetTriple().getOS())
+ case ArchSpec::eCore_mips64:
{
- case llvm::Triple::FreeBSD:
- m_reg_context_sp.reset(new RegisterContextFreeBSD_x86_64(*this, 0));
- break;
- case llvm::Triple::Linux:
- m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
- break;
- default:
- assert(false && "OS not supported");
- break;
+ RegisterInfoInterface *reg_interface = NULL;
+
+ switch (target_arch.GetTriple().getOS())
+ {
+ case llvm::Triple::FreeBSD:
+ reg_interface = new RegisterContextFreeBSD_mips64(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;
}
- 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::FreeBSD:
+ reg_interface = new RegisterContextFreeBSD_x86_64(target_arch);
+ break;
+ case llvm::Triple::Linux:
+ reg_interface = new RegisterContextLinux_x86_64(target_arch);
+ break;
+ default:
+ assert(false && "OS not supported");
+ break;
+ }
+
+ if (reg_interface)
+ {
+ RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ }
+ break;
+ }
+
+ default:
+ assert(false && "CPU type not supported!");
+ break;
}
}
return m_reg_context_sp;
@@ -195,6 +230,17 @@ POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
return reg_ctx_sp;
}
+lldb::addr_t
+POSIXThread::GetThreadPointer ()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ addr_t addr;
+ if (monitor.ReadThreadPointer (GetID(), addr))
+ return addr;
+ else
+ return LLDB_INVALID_ADDRESS;
+}
+
bool
POSIXThread::CalculateStopInfo()
{
@@ -314,6 +360,10 @@ POSIXThread::Notify(const ProcessMessage &message)
case ProcessMessage::eNewThreadMessage:
ThreadNotify(message);
break;
+
+ case ProcessMessage::eExecMessage:
+ ExecNotify(message);
+ break;
}
}
@@ -328,7 +378,7 @@ POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp)
bool wp_read = wp->WatchpointRead();
bool wp_write = wp->WatchpointWrite();
uint32_t wp_hw_index = wp->GetHardwareIndex();
- RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
if (reg_ctx)
wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size,
wp_read, wp_write,
@@ -365,7 +415,7 @@ POSIXThread::FindVacantWatchpointIndex()
uint32_t hw_index = LLDB_INVALID_INDEX32;
uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
uint32_t wp_idx;
- RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
if (reg_ctx)
{
for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
@@ -387,7 +437,7 @@ POSIXThread::BreakNotify(const ProcessMessage &message)
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
assert(GetRegisterContext());
- status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint();
+ status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint();
assert(status && "Breakpoint update failed!");
// With our register state restored, resolve the breakpoint object
@@ -399,31 +449,22 @@ POSIXThread::BreakNotify(const ProcessMessage &message)
lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
// If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
- if (bp_site && bp_site->ValidForThisThread(this))
+ // we create a stop reason with should_stop=false. If there is no breakpoint location, then report
+ // an invalid stop reason. We don't need to worry about stepping over the breakpoint here, that will
+ // be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+ if (bp_site)
{
lldb::break_id_t bp_id = bp_site->GetID();
- if (GetProcess()->GetThreadList().SetSelectedThreadByID(GetID()))
+ if (bp_site->ValidForThisThread(this))
SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
else
- assert(false && "Invalid thread ID during BreakNotify.");
- }
- else
- {
- const ThreadSpec *spec = bp_site ?
- bp_site->GetOwnerAtIndex(0)->GetOptionsNoCreate()->GetThreadSpecNoCreate() : 0;
-
- if (spec && spec->TIDMatches(*this))
- assert(false && "BreakpointSite is invalid for the current ThreadSpec.");
- else
{
- if (!m_stop_info_sp) {
- StopInfoSP invalid_stop_info_sp;
- SetStopInfo (invalid_stop_info_sp);
- }
+ const bool should_stop = false;
+ SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop));
}
}
+ else
+ SetStopInfo(StopInfoSP());
}
void
@@ -436,7 +477,7 @@ POSIXThread::WatchNotify(const ProcessMessage &message)
log->Printf ("POSIXThread::%s () Hardware Watchpoint Address = 0x%8.8"
PRIx64, __FUNCTION__, halt_addr);
- RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
if (reg_ctx)
{
uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
@@ -532,22 +573,26 @@ POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
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:
{
- RegisterContextSP base = GetRegisterContext();
- if (base) {
- RegisterContextPOSIX &context = static_cast<RegisterContextPOSIX &>(*base);
- reg = context.GetRegisterIndexFromOffset(offset);
- }
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ reg = reg_ctx->GetRegisterIndexFromOffset(offset);
}
break;
}
return reg;
}
+void
+POSIXThread::ExecNotify(const ProcessMessage &message)
+{
+ SetStopInfo (StopInfo::CreateStopReasonWithExec(*this));
+}
+
const char *
POSIXThread::GetRegisterName(unsigned reg)
{
@@ -560,6 +605,7 @@ POSIXThread::GetRegisterName(unsigned reg)
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:
diff --git a/source/Plugins/Process/POSIX/POSIXThread.h b/source/Plugins/Process/POSIX/POSIXThread.h
index d051d23860df..51d6645f209d 100644
--- a/source/Plugins/Process/POSIX/POSIXThread.h
+++ b/source/Plugins/Process/POSIX/POSIXThread.h
@@ -21,7 +21,7 @@
class ProcessMessage;
class ProcessMonitor;
-class RegisterContextPOSIX;
+class POSIXBreakpointProtocol;
//------------------------------------------------------------------------------
// @class POSIXThread
@@ -59,6 +59,9 @@ public:
virtual lldb::RegisterContextSP
CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+ virtual lldb::addr_t
+ GetThreadPointer ();
+
//--------------------------------------------------------------------------
// These functions provide a mapping from the register offset
// back to the register index or name for use in debugging or log
@@ -92,15 +95,12 @@ public:
uint32_t FindVacantWatchpointIndex();
protected:
- RegisterContextPOSIX *
- GetRegisterContextPOSIX ()
+ POSIXBreakpointProtocol *
+ GetPOSIXBreakpointProtocol ()
{
if (!m_reg_context_sp)
m_reg_context_sp = GetRegisterContext();
-#if 0
- return dynamic_cast<RegisterContextPOSIX*>(m_reg_context_sp.get());
-#endif
- return (RegisterContextPOSIX *)m_reg_context_sp.get();
+ return m_posix_thread;
}
std::unique_ptr<lldb_private::StackFrame> m_frame_ap;
@@ -109,6 +109,7 @@ protected:
bool m_thread_name_valid;
std::string m_thread_name;
+ POSIXBreakpointProtocol *m_posix_thread;
ProcessMonitor &
GetMonitor();
@@ -125,6 +126,7 @@ protected:
void CrashNotify(const ProcessMessage &message);
void ThreadNotify(const ProcessMessage &message);
void ExitNotify(const ProcessMessage &message);
+ void ExecNotify(const ProcessMessage &message);
lldb_private::Unwind *
GetUnwinder();
diff --git a/source/Plugins/Process/POSIX/ProcessMessage.cpp b/source/Plugins/Process/POSIX/ProcessMessage.cpp
index 60a29e07cea8..5c53627f9e0b 100644
--- a/source/Plugins/Process/POSIX/ProcessMessage.cpp
+++ b/source/Plugins/Process/POSIX/ProcessMessage.cpp
@@ -218,6 +218,9 @@ ProcessMessage::PrintKind(Kind kind)
case eInvalidMessage:
str = "eInvalidMessage";
break;
+ case eAttachMessage:
+ str = "eAttachMessage";
+ break;
case eExitMessage:
str = "eExitMessage";
break;
@@ -245,6 +248,9 @@ ProcessMessage::PrintKind(Kind kind)
case eNewThreadMessage:
str = "eNewThreadMessage";
break;
+ case eExecMessage:
+ str = "eExecMessage";
+ break;
}
#endif
diff --git a/source/Plugins/Process/POSIX/ProcessMessage.h b/source/Plugins/Process/POSIX/ProcessMessage.h
index c6c460c13445..40462d0f0e13 100644
--- a/source/Plugins/Process/POSIX/ProcessMessage.h
+++ b/source/Plugins/Process/POSIX/ProcessMessage.h
@@ -23,6 +23,7 @@ public:
enum Kind
{
eInvalidMessage,
+ eAttachMessage,
eExitMessage,
eLimboMessage,
eSignalMessage,
@@ -31,7 +32,8 @@ public:
eBreakpointMessage,
eWatchpointMessage,
eCrashMessage,
- eNewThreadMessage
+ eNewThreadMessage,
+ eExecMessage
};
enum CrashReason
@@ -79,6 +81,11 @@ public:
lldb::tid_t GetTID() const { return m_tid; }
+ /// Indicates that the process @p pid has successfully attached.
+ static ProcessMessage Attach(lldb::pid_t pid) {
+ return ProcessMessage(pid, eAttachMessage);
+ }
+
/// Indicates that the thread @p tid is about to exit with status @p status.
static ProcessMessage Limbo(lldb::tid_t tid, int status) {
return ProcessMessage(tid, eLimboMessage, status);
@@ -127,6 +134,11 @@ public:
return ProcessMessage(tid, eExitMessage, status);
}
+ /// Indicates that the thread @p pid has exec'd.
+ static ProcessMessage Exec(lldb::tid_t tid) {
+ return ProcessMessage(tid, eExecMessage);
+ }
+
int GetExitStatus() const {
assert(GetKind() == eExitMessage || GetKind() == eLimboMessage);
return m_status;
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
index f04631ddf914..70ad3a66d9ef 100644
--- a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -289,12 +289,11 @@ ProcessPOSIX::GetImageInfoAddress()
{
Target *target = &GetTarget();
ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
- Address addr = obj_file->GetImageInfoAddress();
+ Address addr = obj_file->GetImageInfoAddress(target);
- if (addr.IsValid())
+ if (addr.IsValid())
return addr.GetLoadAddress(target);
- else
- return LLDB_INVALID_ADDRESS;
+ return LLDB_INVALID_ADDRESS;
}
Error
@@ -319,34 +318,6 @@ ProcessPOSIX::DoHalt(bool &caused_stop)
}
Error
-ProcessPOSIX::DoDetach(bool keep_stopped)
-{
- Error error;
- if (keep_stopped)
- {
- // FIXME: If you want to implement keep_stopped,
- // this would be the place to do it.
- error.SetErrorString("Detaching with keep_stopped true is not currently supported on this platform.");
- return error;
- }
-
- Mutex::Locker lock(m_thread_list.GetMutex());
-
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i)
- {
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- error = m_monitor->Detach(thread->GetID());
- }
-
- if (error.Success())
- SetPrivateState(eStateDetached);
-
- return error;
-}
-
-Error
ProcessPOSIX::DoSignal(int signal)
{
Error error;
@@ -381,6 +352,31 @@ ProcessPOSIX::DoDestroy()
}
void
+ProcessPOSIX::DoDidExec()
+{
+ Target *target = &GetTarget();
+ if (target)
+ {
+ PlatformSP platform_sp (target->GetPlatform());
+ assert (platform_sp.get());
+ if (platform_sp)
+ {
+ ProcessInstanceInfo process_info;
+ platform_sp->GetProcessInfo(GetID(), process_info);
+ ModuleSP exe_module_sp;
+ FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
+ Error error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(),
+ target->GetArchitecture(),
+ exe_module_sp,
+ executable_search_paths.GetSize() ? &executable_search_paths : NULL);
+ if (!error.Success())
+ return;
+ target->SetExecutableModule(exe_module_sp, true);
+ }
+ }
+}
+
+void
ProcessPOSIX::SendMessage(const ProcessMessage &message)
{
Mutex::Locker lock(m_message_mutex);
@@ -395,6 +391,10 @@ ProcessPOSIX::SendMessage(const ProcessMessage &message)
case ProcessMessage::eInvalidMessage:
return;
+ case ProcessMessage::eAttachMessage:
+ SetPrivateState(eStateStopped);
+ return;
+
case ProcessMessage::eLimboMessage:
assert(thread);
thread->SetState(eStateStopped);
@@ -442,15 +442,38 @@ ProcessPOSIX::SendMessage(const ProcessMessage &message)
case ProcessMessage::eBreakpointMessage:
case ProcessMessage::eTraceMessage:
case ProcessMessage::eWatchpointMessage:
- case ProcessMessage::eNewThreadMessage:
case ProcessMessage::eCrashMessage:
assert(thread);
thread->SetState(eStateStopped);
StopAllThreads(message.GetTID());
SetPrivateState(eStateStopped);
break;
+
+ case ProcessMessage::eNewThreadMessage:
+ {
+ lldb::tid_t new_tid = message.GetChildTID();
+ if (WaitingForInitialStop(new_tid))
+ {
+ m_monitor->WaitForInitialTIDStop(new_tid);
+ }
+ assert(thread);
+ thread->SetState(eStateStopped);
+ StopAllThreads(message.GetTID());
+ SetPrivateState(eStateStopped);
+ break;
}
+ case ProcessMessage::eExecMessage:
+ {
+ assert(thread);
+ thread->SetState(eStateStopped);
+ StopAllThreads(message.GetTID());
+ SetPrivateState(eStateStopped);
+ break;
+ }
+ }
+
+
m_message_queue.push(message);
}
@@ -473,6 +496,12 @@ ProcessPOSIX::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid)
return added_to_set;
}
+bool
+ProcessPOSIX::WaitingForInitialStop(lldb::tid_t stop_tid)
+{
+ return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
+}
+
POSIXThread *
ProcessPOSIX::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid)
{
@@ -499,8 +528,6 @@ ProcessPOSIX::RefreshStateAfterStop()
lldb::tid_t tid = message.GetTID();
if (log)
log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
- POSIXThread *thread = static_cast<POSIXThread*>(
- GetThreadList().FindThreadByID(tid, false).get());
if (message.GetKind() == ProcessMessage::eNewThreadMessage)
{
@@ -517,6 +544,8 @@ ProcessPOSIX::RefreshStateAfterStop()
m_thread_list.RefreshStateAfterStop();
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ GetThreadList().FindThreadByID(tid, false).get());
if (thread)
thread->Notify(message);
@@ -813,19 +842,21 @@ ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thre
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
log->Printf ("ProcessPOSIX::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID());
+ bool has_updated = false;
// Update the process thread list with this new thread.
// FIXME: We should be using tid, not pid.
assert(m_monitor);
ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
if (!thread_sp) {
thread_sp.reset(CreateNewPOSIXThread(*this, GetID()));
+ has_updated = true;
}
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
log->Printf ("ProcessPOSIX::%s() updated pid = %" PRIi64, __FUNCTION__, GetID());
new_thread_list.AddThread(thread_sp);
- return new_thread_list.GetSize(false) > 0;
+ return has_updated; // the list has been updated
}
ByteOrder
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.h b/source/Plugins/Process/POSIX/ProcessPOSIX.h
index 48b19bac47e7..790041be321a 100644
--- a/source/Plugins/Process/POSIX/ProcessPOSIX.h
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.h
@@ -70,7 +70,7 @@ public:
DoHalt(bool &caused_stop);
virtual lldb_private::Error
- DoDetach(bool keep_stopped);
+ DoDetach(bool keep_stopped) = 0;
virtual lldb_private::Error
DoSignal(int signal);
@@ -79,6 +79,9 @@ public:
DoDestroy();
virtual void
+ DoDidExec();
+
+ virtual void
RefreshStateAfterStop();
virtual bool
@@ -167,6 +170,9 @@ public:
bool
AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
+ bool
+ WaitingForInitialStop(lldb::tid_t stop_tid);
+
virtual POSIXThread *
CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid);
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp
new file mode 100644
index 000000000000..50ec8d414a12
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp
@@ -0,0 +1,78 @@
+//===-- RegisterContextFreeBSD_i386.cpp ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "RegisterContextPOSIX_x86.h"
+#include "RegisterContextFreeBSD_i386.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+// http://svnweb.freebsd.org/base/head/sys/x86/include/reg.h
+struct GPR
+{
+ uint32_t fs;
+ uint32_t es;
+ uint32_t ds;
+ uint32_t edi;
+ uint32_t esi;
+ uint32_t ebp;
+ uint32_t isp;
+ uint32_t ebx;
+ uint32_t edx;
+ uint32_t ecx;
+ uint32_t eax;
+ uint32_t trapno;
+ uint32_t err;
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t eflags;
+ uint32_t esp;
+ uint32_t ss;
+ uint32_t gs;
+};
+
+#define DR_SIZE 0
+#define DR_OFFSET(reg_index) 0
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_i386 to declare our g_register_infos_i386 structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_I386_STRUCT
+#include "RegisterInfos_i386.h"
+#undef DECLARE_REGISTER_INFOS_I386_STRUCT
+
+RegisterContextFreeBSD_i386::RegisterContextFreeBSD_i386(const ArchSpec &target_arch) :
+ RegisterInfoInterface(target_arch)
+{
+}
+
+RegisterContextFreeBSD_i386::~RegisterContextFreeBSD_i386()
+{
+}
+
+size_t
+RegisterContextFreeBSD_i386::GetGPRSize()
+{
+ return sizeof(GPR);
+}
+
+const RegisterInfo *
+RegisterContextFreeBSD_i386::GetRegisterInfo()
+{
+ switch (m_target_arch.GetCore())
+ {
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ return g_register_infos_i386;
+ default:
+ assert(false && "Unhandled target architecture.");
+ return NULL;
+ }
+}
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h
new file mode 100644
index 000000000000..4ec2ad3e9706
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h
@@ -0,0 +1,29 @@
+//===-- RegisterContextFreeBSD_i386.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextFreeBSD_i386_H_
+#define liblldb_RegisterContextFreeBSD_i386_H_
+
+#include "RegisterContextPOSIX.h"
+
+class RegisterContextFreeBSD_i386
+ : public RegisterInfoInterface
+{
+public:
+ RegisterContextFreeBSD_i386(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextFreeBSD_i386();
+
+ size_t
+ GetGPRSize();
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo();
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp
new file mode 100644
index 000000000000..4714251fd2dc
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp
@@ -0,0 +1,90 @@
+//===-- RegisterContextFreeBSD_mips64.cpp ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include <vector>
+#include "RegisterContextPOSIX_mips64.h"
+#include "RegisterContextFreeBSD_mips64.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+// http://svnweb.freebsd.org/base/head/sys/mips/include/regnum.h
+typedef struct _GPR
+{
+ uint64_t zero;
+ uint64_t r1;
+ uint64_t r2;
+ uint64_t r3;
+ uint64_t r4;
+ uint64_t r5;
+ uint64_t r6;
+ uint64_t r7;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t r16;
+ uint64_t r17;
+ uint64_t r18;
+ uint64_t r19;
+ uint64_t r20;
+ uint64_t r21;
+ uint64_t r22;
+ uint64_t r23;
+ uint64_t r24;
+ uint64_t r25;
+ uint64_t r26;
+ uint64_t r27;
+ uint64_t gp;
+ uint64_t sp;
+ uint64_t r30;
+ uint64_t ra;
+ uint64_t sr;
+ uint64_t mullo;
+ uint64_t mulhi;
+ uint64_t badvaddr;
+ uint64_t cause;
+ uint64_t pc;
+ uint64_t ic;
+ uint64_t dummy;
+} GPR;
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_mips64 to declare our g_register_infos_mips64 structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_MIPS64_STRUCT
+#include "RegisterInfos_mips64.h"
+#undef DECLARE_REGISTER_INFOS_MIPS64_STRUCT
+
+RegisterContextFreeBSD_mips64::RegisterContextFreeBSD_mips64(const ArchSpec &target_arch) :
+ RegisterInfoInterface(target_arch)
+{
+}
+
+RegisterContextFreeBSD_mips64::~RegisterContextFreeBSD_mips64()
+{
+}
+
+size_t
+RegisterContextFreeBSD_mips64::GetGPRSize()
+{
+ return sizeof(GPR);
+}
+
+const RegisterInfo *
+RegisterContextFreeBSD_mips64::GetRegisterInfo()
+{
+ assert (m_target_arch.GetCore() == ArchSpec::eCore_mips64);
+ return g_register_infos_mips64;
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h
new file mode 100644
index 000000000000..9ee767955347
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h
@@ -0,0 +1,29 @@
+//===-- RegisterContextFreeBSD_mips64.h -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextFreeBSD_mips64_H_
+#define liblldb_RegisterContextFreeBSD_mips64_H_
+
+#include "RegisterContextPOSIX.h"
+
+class RegisterContextFreeBSD_mips64:
+ public RegisterInfoInterface
+{
+public:
+ RegisterContextFreeBSD_mips64(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextFreeBSD_mips64();
+
+ size_t
+ GetGPRSize();
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo();
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
index 0fb9dc1cb3dc..471734580fff 100644
--- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
@@ -1,4 +1,4 @@
-//===-- RegisterContextFreeBSD_x86_64.h ------------------------*- C++ -*-===//
+//===-- RegisterContextFreeBSD_x86_64.cpp ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,27 +7,15 @@
//
//===---------------------------------------------------------------------===//
-#include "RegisterContextFreeBSD_x86_64.h"
#include <vector>
+#include "RegisterContextPOSIX_x86.h"
+#include "RegisterContextFreeBSD_i386.h"
+#include "RegisterContextFreeBSD_x86_64.h"
using namespace lldb_private;
+using namespace lldb;
-// Computes the offset of the given GPR in the user data area.
-#define GPR_OFFSET(regname) \
- (offsetof(GPR, regname))
-
-// Update the FreeBSD specific information (offset and size).
-#define UPDATE_GPR_INFO(reg) \
-do { \
- GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg); \
- GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
-} while(false);
-
-#define UPDATE_I386_GPR_INFO(i386_reg, reg) \
-do { \
- GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
-} while(false);
-
+// http://svnweb.freebsd.org/base/head/sys/x86/include/reg.h
typedef struct _GPR
{
uint64_t r15;
@@ -58,15 +46,47 @@ typedef struct _GPR
uint64_t ss;
} GPR;
-// Use a singleton function to avoid global constructors in shared libraries.
-static std::vector<RegisterInfo> & GetRegisterContext () {
- static std::vector<RegisterInfo> g_register_infos;
- return g_register_infos;
+#define DR_SIZE 0
+#define DR_OFFSET(reg_index) 0
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_X86_64_STRUCT
+#include "RegisterInfos_x86_64.h"
+#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
+
+static const RegisterInfo *
+GetRegisterInfo_i386(const lldb_private::ArchSpec& arch)
+{
+ static std::vector<lldb_private::RegisterInfo> g_register_infos;
+
+ // Allocate RegisterInfo only once
+ if (g_register_infos.empty())
+ {
+ // Copy the register information from base class
+ std::unique_ptr<RegisterContextFreeBSD_i386> reg_interface(new RegisterContextFreeBSD_i386 (arch));
+ const RegisterInfo *base_info = reg_interface->GetRegisterInfo();
+ g_register_infos.insert(g_register_infos.end(), &base_info[0], &base_info[k_num_registers_i386]);
+
+ //---------------------------------------------------------------------------
+ // Include RegisterInfos_x86_64 to update the g_register_infos structure
+ // with x86_64 offsets.
+ //---------------------------------------------------------------------------
+ #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+ #include "RegisterInfos_x86_64.h"
+ #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+ }
+
+ return &g_register_infos[0];
}
+RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(const ArchSpec &target_arch) :
+ RegisterInfoInterface(target_arch)
+{
+}
-RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(Thread &thread, uint32_t concrete_frame_idx):
- RegisterContext_x86_64(thread, concrete_frame_idx)
+RegisterContextFreeBSD_x86_64::~RegisterContextFreeBSD_x86_64()
{
}
@@ -79,58 +99,17 @@ RegisterContextFreeBSD_x86_64::GetGPRSize()
const RegisterInfo *
RegisterContextFreeBSD_x86_64::GetRegisterInfo()
{
- // Allocate RegisterInfo only once
- if (GetRegisterContext().empty())
+ switch (m_target_arch.GetCore())
{
- // Copy the register information from base class
- const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
- if (base_info)
- {
- GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
- // Update the FreeBSD specific register information (offset and size).
- UpdateRegisterInfo();
- }
+ 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 &GetRegisterContext()[0];
-}
-
-void
-RegisterContextFreeBSD_x86_64::UpdateRegisterInfo()
-{
- UPDATE_GPR_INFO(rax);
- UPDATE_GPR_INFO(rbx);
- UPDATE_GPR_INFO(rcx);
- UPDATE_GPR_INFO(rdx);
- UPDATE_GPR_INFO(rdi);
- UPDATE_GPR_INFO(rsi);
- UPDATE_GPR_INFO(rbp);
- UPDATE_GPR_INFO(rsp);
- UPDATE_GPR_INFO(r8);
- UPDATE_GPR_INFO(r9);
- UPDATE_GPR_INFO(r10);
- UPDATE_GPR_INFO(r11);
- UPDATE_GPR_INFO(r12);
- UPDATE_GPR_INFO(r13);
- UPDATE_GPR_INFO(r14);
- UPDATE_GPR_INFO(r15);
- UPDATE_GPR_INFO(rip);
- UPDATE_GPR_INFO(rflags);
- UPDATE_GPR_INFO(cs);
- UPDATE_GPR_INFO(fs);
- UPDATE_GPR_INFO(gs);
- UPDATE_GPR_INFO(ss);
- UPDATE_GPR_INFO(ds);
- UPDATE_GPR_INFO(es);
-
- UPDATE_I386_GPR_INFO(eax, rax);
- UPDATE_I386_GPR_INFO(ebx, rbx);
- UPDATE_I386_GPR_INFO(ecx, rcx);
- UPDATE_I386_GPR_INFO(edx, rdx);
- UPDATE_I386_GPR_INFO(edi, rdi);
- UPDATE_I386_GPR_INFO(esi, rsi);
- UPDATE_I386_GPR_INFO(ebp, rbp);
- UPDATE_I386_GPR_INFO(esp, rsp);
- UPDATE_I386_GPR_INFO(eip, rip);
- UPDATE_I386_GPR_INFO(eflags, rflags);
}
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h
index ffff40a9c65b..731bb0ea6bcc 100644
--- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h
@@ -1,4 +1,4 @@
-//===-- RegisterContextFreeBSD_x86_64.h ---------------------------*- C++ -*-===//
+//===-- RegisterContextFreeBSD_x86_64.h -------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,23 +10,20 @@
#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_
#define liblldb_RegisterContextFreeBSD_x86_64_H_
-#include "Plugins/Process/POSIX/RegisterContext_x86_64.h"
+#include "RegisterContextPOSIX.h"
class RegisterContextFreeBSD_x86_64:
- public RegisterContext_x86_64
+ public RegisterInfoInterface
{
public:
- RegisterContextFreeBSD_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+ RegisterContextFreeBSD_x86_64(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextFreeBSD_x86_64();
size_t
GetGPRSize();
-protected:
- virtual const lldb_private::RegisterInfo *
+ const lldb_private::RegisterInfo *
GetRegisterInfo();
-
- virtual void
- UpdateRegisterInfo();
};
#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp b/source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp
new file mode 100644
index 000000000000..0828efbc6c3c
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp
@@ -0,0 +1,96 @@
+//===-- RegisterContextLinux_i386.cpp --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "RegisterContextPOSIX_x86.h"
+#include "RegisterContextLinux_i386.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+struct GPR
+{
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t esi;
+ uint32_t edi;
+ uint32_t ebp;
+ uint32_t eax;
+ uint32_t ds;
+ uint32_t es;
+ uint32_t fs;
+ uint32_t gs;
+ uint32_t orig_ax;
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t eflags;
+ uint32_t esp;
+ uint32_t ss;
+};
+
+struct UserArea
+{
+ GPR regs; // General purpose registers.
+ int32_t fpvalid; // True if FPU is being used.
+ FXSAVE i387; // FPU registers.
+ uint32_t tsize; // Text segment size.
+ uint32_t dsize; // Data segment size.
+ uint32_t ssize; // Stack segment size.
+ uint32_t start_code; // VM address of text.
+ uint32_t start_stack; // VM address of stack bottom (top in rsp).
+ int32_t signal; // Signal causing core dump.
+ int32_t reserved; // Unused.
+ uint32_t ar0; // Location of GPR's.
+ uint32_t fpstate; // Location of FPR's. Should be a FXSTATE *, but this
+ // has to be 32-bits even on 64-bit systems.
+ uint32_t magic; // Identifier for core dumps.
+ char u_comm[32]; // Command causing core dump.
+ uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7).
+};
+
+#define DR_SIZE sizeof(UserArea::u_debugreg[0])
+#define DR_OFFSET(reg_index) \
+ (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index]))
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_i386 to declare our g_register_infos_i386 structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_I386_STRUCT
+#include "RegisterInfos_i386.h"
+#undef DECLARE_REGISTER_INFOS_I386_STRUCT
+
+RegisterContextLinux_i386::RegisterContextLinux_i386(const ArchSpec &target_arch) :
+ RegisterInfoInterface(target_arch)
+{
+}
+
+RegisterContextLinux_i386::~RegisterContextLinux_i386()
+{
+}
+
+size_t
+RegisterContextLinux_i386::GetGPRSize()
+{
+ return sizeof(GPR);
+}
+
+const RegisterInfo *
+RegisterContextLinux_i386::GetRegisterInfo()
+{
+ switch (m_target_arch.GetCore())
+ {
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ return g_register_infos_i386;
+ default:
+ assert(false && "Unhandled target architecture.");
+ return NULL;
+ }
+}
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_i386.h b/source/Plugins/Process/POSIX/RegisterContextLinux_i386.h
new file mode 100644
index 000000000000..81afdbf8b1cf
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextLinux_i386.h
@@ -0,0 +1,29 @@
+//===-- RegisterContextLinux_i386.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_i386_H_
+#define liblldb_RegisterContextLinux_i386_H_
+
+#include "RegisterContextPOSIX.h"
+
+class RegisterContextLinux_i386
+ : public RegisterInfoInterface
+{
+public:
+ RegisterContextLinux_i386(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextLinux_i386();
+
+ size_t
+ GetGPRSize();
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo();
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp
index c1aea2a41a1f..5434ddfcf38b 100644
--- a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp
+++ b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp
@@ -1,4 +1,4 @@
-//===-- RegisterContextLinux_x86_64.h --------------------------*- C++ -*-===//
+//===-- RegisterContextLinux_x86_64.cpp ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,36 +7,13 @@
//
//===---------------------------------------------------------------------===//
-#include "llvm/Support/Compiler.h"
-#include "RegisterContextLinux_x86_64.h"
#include <vector>
+#include "RegisterContextPOSIX_x86.h"
+#include "RegisterContextLinux_i386.h"
+#include "RegisterContextLinux_x86_64.h"
using namespace lldb_private;
-
-// Computes the offset of the given GPR in the user data area.
-#define GPR_OFFSET(regname) \
- (offsetof(GPR, regname))
-
-// Update the Linux specific information (offset and size).
-#define UPDATE_GPR_INFO(reg) \
-do { \
- GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg); \
- GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
-} while(false);
-
-#define UPDATE_I386_GPR_INFO(i386_reg, reg) \
-do { \
- GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
-} while(false);
-
-#define DR_OFFSET(reg_index) \
- (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index]))
-
-#define UPDATE_DR_INFO(reg_index) \
-do { \
- GetRegisterContext()[dr##reg_index].byte_size = sizeof(UserArea::u_debugreg[0]); \
- GetRegisterContext()[dr##reg_index].byte_offset = DR_OFFSET(reg_index); \
-} while(false);
+using namespace lldb;
typedef struct _GPR
{
@@ -69,8 +46,6 @@ typedef struct _GPR
uint64_t gs;
} GPR;
-typedef RegisterContext_x86_64::FXSAVE FXSAVE;
-
struct UserArea
{
GPR gpr; // General purpose registers.
@@ -94,14 +69,48 @@ struct UserArea
uint64_t fault_address; // Control register CR3.
};
-// Use a singleton function to avoid global constructors in shared libraries.
-static std::vector<RegisterInfo> & GetRegisterContext () {
- static std::vector<RegisterInfo> g_register_infos;
- return g_register_infos;
+#define DR_SIZE sizeof(UserArea::u_debugreg[0])
+#define DR_OFFSET(reg_index) \
+ (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index]))
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_X86_64_STRUCT
+#include "RegisterInfos_x86_64.h"
+#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
+
+static const RegisterInfo *
+GetRegisterInfo_i386(const lldb_private::ArchSpec &arch)
+{
+ static std::vector<lldb_private::RegisterInfo> g_register_infos;
+
+ // Allocate RegisterInfo only once
+ if (g_register_infos.empty())
+ {
+ // Copy the register information from base class
+ std::unique_ptr<RegisterContextLinux_i386> reg_interface(new RegisterContextLinux_i386 (arch));
+ const RegisterInfo *base_info = reg_interface->GetRegisterInfo();
+ g_register_infos.insert(g_register_infos.end(), &base_info[0], &base_info[k_num_registers_i386]);
+
+ //---------------------------------------------------------------------------
+ // Include RegisterInfos_x86_64 to update the g_register_infos structure
+ // with x86_64 offsets.
+ //---------------------------------------------------------------------------
+ #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+ #include "RegisterInfos_x86_64.h"
+ #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+ }
+
+ return &g_register_infos[0];
+}
+
+RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) :
+ RegisterInfoInterface(target_arch)
+{
}
-RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, uint32_t concrete_frame_idx):
- RegisterContext_x86_64(thread, concrete_frame_idx)
+RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64()
{
}
@@ -114,67 +123,17 @@ RegisterContextLinux_x86_64::GetGPRSize()
const RegisterInfo *
RegisterContextLinux_x86_64::GetRegisterInfo()
{
- // Allocate RegisterInfo only once
- if (GetRegisterContext().empty())
+ switch (m_target_arch.GetCore())
{
- // Copy the register information from base class
- const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
- if (base_info)
- {
- GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
- // Update the Linux specific register information (offset and size).
- UpdateRegisterInfo();
- }
+ 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 &GetRegisterContext()[0];
-}
-
-void
-RegisterContextLinux_x86_64::UpdateRegisterInfo()
-{
- UPDATE_GPR_INFO(rax);
- UPDATE_GPR_INFO(rbx);
- UPDATE_GPR_INFO(rcx);
- UPDATE_GPR_INFO(rdx);
- UPDATE_GPR_INFO(rdi);
- UPDATE_GPR_INFO(rsi);
- UPDATE_GPR_INFO(rbp);
- UPDATE_GPR_INFO(rsp);
- UPDATE_GPR_INFO(r8);
- UPDATE_GPR_INFO(r9);
- UPDATE_GPR_INFO(r10);
- UPDATE_GPR_INFO(r11);
- UPDATE_GPR_INFO(r12);
- UPDATE_GPR_INFO(r13);
- UPDATE_GPR_INFO(r14);
- UPDATE_GPR_INFO(r15);
- UPDATE_GPR_INFO(rip);
- UPDATE_GPR_INFO(rflags);
- UPDATE_GPR_INFO(cs);
- UPDATE_GPR_INFO(fs);
- UPDATE_GPR_INFO(gs);
- UPDATE_GPR_INFO(ss);
- UPDATE_GPR_INFO(ds);
- UPDATE_GPR_INFO(es);
-
- UPDATE_I386_GPR_INFO(eax, rax);
- UPDATE_I386_GPR_INFO(ebx, rbx);
- UPDATE_I386_GPR_INFO(ecx, rcx);
- UPDATE_I386_GPR_INFO(edx, rdx);
- UPDATE_I386_GPR_INFO(edi, rdi);
- UPDATE_I386_GPR_INFO(esi, rsi);
- UPDATE_I386_GPR_INFO(ebp, rbp);
- UPDATE_I386_GPR_INFO(esp, rsp);
- UPDATE_I386_GPR_INFO(eip, rip);
- UPDATE_I386_GPR_INFO(eflags, rflags);
-
- UPDATE_DR_INFO(0);
- UPDATE_DR_INFO(1);
- UPDATE_DR_INFO(2);
- UPDATE_DR_INFO(3);
- UPDATE_DR_INFO(4);
- UPDATE_DR_INFO(5);
- UPDATE_DR_INFO(6);
- UPDATE_DR_INFO(7);
}
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h
index 1509ef55b8dc..21c809b5dc33 100644
--- a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h
+++ b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h
@@ -10,23 +10,20 @@
#ifndef liblldb_RegisterContextLinux_x86_64_H_
#define liblldb_RegisterContextLinux_x86_64_H_
-#include "Plugins/Process/POSIX/RegisterContext_x86_64.h"
+#include "RegisterContextPOSIX.h"
-class RegisterContextLinux_x86_64:
- public RegisterContext_x86_64
+class RegisterContextLinux_x86_64
+ : public RegisterInfoInterface
{
public:
- RegisterContextLinux_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+ RegisterContextLinux_x86_64(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextLinux_x86_64();
size_t
GetGPRSize();
-protected:
- virtual const lldb_private::RegisterInfo *
+ const lldb_private::RegisterInfo *
GetRegisterInfo();
-
- virtual void
- UpdateRegisterInfo();
};
#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX.h b/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
index 63ae01e83a90..e48c528403e3 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
@@ -13,20 +13,19 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
#include "lldb/Target/RegisterContext.h"
//------------------------------------------------------------------------------
-/// @class RegisterContextPOSIX
+/// @class POSIXBreakpointProtocol
///
/// @brief Extends RegisterClass with a few virtual operations useful on POSIX.
-class RegisterContextPOSIX
- : public lldb_private::RegisterContext
+class POSIXBreakpointProtocol
{
public:
- RegisterContextPOSIX(lldb_private::Thread &thread,
- uint32_t concrete_frame_idx)
- : RegisterContext(thread, concrete_frame_idx)
+ POSIXBreakpointProtocol()
{ m_watchpoints_initialized = false; }
+ virtual ~POSIXBreakpointProtocol() {}
/// Updates the register state of the associated thread after hitting a
/// breakpoint (if that make sense for the architecture). Default
@@ -35,36 +34,61 @@ public:
///
/// @return
/// True if the operation succeeded and false otherwise.
- virtual bool UpdateAfterBreakpoint() { return true; }
+ virtual bool UpdateAfterBreakpoint() = 0;
/// Determines the index in lldb's register file given a kernel byte offset.
virtual unsigned
- GetRegisterIndexFromOffset(unsigned offset) { return LLDB_INVALID_REGNUM; }
+ GetRegisterIndexFromOffset(unsigned offset) = 0;
// Checks to see if a watchpoint specified by hw_index caused the inferior
// to stop.
virtual bool
- IsWatchpointHit (uint32_t hw_index) { return false; }
+ IsWatchpointHit (uint32_t hw_index) = 0;
// Resets any watchpoints that have been hit.
virtual bool
- ClearWatchpointHits () { return false; }
+ ClearWatchpointHits () = 0;
// Returns the watchpoint address associated with a watchpoint hardware
// index.
virtual lldb::addr_t
- GetWatchpointAddress (uint32_t hw_index) { return LLDB_INVALID_ADDRESS; }
+ GetWatchpointAddress (uint32_t hw_index) = 0;
virtual bool
- IsWatchpointVacant (uint32_t hw_index) { return false; }
+ IsWatchpointVacant (uint32_t hw_index) = 0;
virtual bool
SetHardwareWatchpointWithIndex (lldb::addr_t addr, size_t size,
bool read, bool write,
- uint32_t hw_index) { return false; }
+ uint32_t hw_index) = 0;
+
+ // From lldb_private::RegisterContext
+ virtual uint32_t
+ NumSupportedHardwareWatchpoints () = 0;
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/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp
new file mode 100644
index 000000000000..f70d00e98a3e
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp
@@ -0,0 +1,318 @@
+//===-- RegisterContextPOSIXProcessMonitor_mips64.h ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "lldb/Target/Thread.h"
+#include "lldb/Core/RegisterValue.h"
+
+#include "RegisterContextPOSIX_mips64.h"
+#include "ProcessPOSIX.h"
+#include "RegisterContextPOSIXProcessMonitor_mips64.h"
+#include "ProcessMonitor.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+#define REG_CONTEXT_SIZE (GetGPRSize())
+
+RegisterContextPOSIXProcessMonitor_mips64::RegisterContextPOSIXProcessMonitor_mips64(Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info)
+ : RegisterContextPOSIX_mips64(thread, concrete_frame_idx, register_info)
+{
+}
+
+ProcessMonitor &
+RegisterContextPOSIXProcessMonitor_mips64::GetMonitor()
+{
+ ProcessSP base = CalculateProcess();
+ ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ return process->GetMonitor();
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ReadGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ReadFPR()
+{
+ // XXX not yet implemented
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::WriteGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::WriteFPR()
+{
+ // XXX not yet implemented
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(const unsigned reg,
+ RegisterValue &value)
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg),
+ GetRegisterName(reg),
+ GetRegisterSize(reg),
+ value);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(const unsigned reg,
+ const RegisterValue &value)
+{
+ unsigned reg_to_write = reg;
+ RegisterValue value_to_write = value;
+
+ // Check if this is a subregister of a full register.
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
+ if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
+ {
+ RegisterValue full_value;
+ uint32_t full_reg = reg_info->invalidate_regs[0];
+ const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
+
+ // Read the full register.
+ if (ReadRegister(full_reg_info, full_value))
+ {
+ Error error;
+ ByteOrder byte_order = GetByteOrder();
+ uint8_t dst[RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the full register.
+ const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
+ dst,
+ sizeof(dst),
+ byte_order,
+ error);
+ if (error.Success() && dest_size)
+ {
+ uint8_t src[RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the source data.
+ const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
+ if (error.Success() && src_size && (src_size < dest_size))
+ {
+ // Copy the src bytes to the destination.
+ memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
+ // Set this full register as the value to write.
+ value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
+ value_to_write.SetType(full_reg_info);
+ reg_to_write = full_reg;
+ }
+ }
+ }
+ }
+
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg_to_write),
+ GetRegisterName(reg_to_write),
+ value_to_write);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+ if (!reg_info)
+ return false;
+
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+ if (IsFPR(reg))
+ {
+ if (!ReadFPR())
+ return false;
+ }
+ else
+ {
+ uint32_t full_reg = reg;
+ bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
+
+ if (is_subreg)
+ {
+ // Read the full aligned 64-bit register.
+ full_reg = reg_info->invalidate_regs[0];
+ }
+
+ bool success = ReadRegister(full_reg, value);
+
+ if (success)
+ {
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
+ if (is_subreg && (reg_info->byte_offset & 0x1))
+ value.SetUInt64(value.GetAsUInt64() >> 8);
+
+ // If our return byte size was greater than the return value reg size, then
+ // use the type specified by reg_info rather than the uint64_t default
+ if (value.GetByteSize() > reg_info->byte_size)
+ value.SetType(reg_info);
+ }
+ return success;
+ }
+
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+ if (IsGPR(reg))
+ return WriteRegister(reg, value);
+
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ReadAllRegisterValues(DataBufferSP &data_sp)
+{
+ bool success = false;
+ data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+ if (data_sp && ReadGPR () && ReadFPR ())
+ {
+ uint8_t *dst = data_sp->GetBytes();
+ success = dst != 0;
+
+ if (success)
+ {
+ ::memcpy (dst, &m_gpr_mips64, GetGPRSize());
+ dst += GetGPRSize();
+ }
+ }
+ return success;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::WriteAllRegisterValues(const DataBufferSP &data_sp)
+{
+ bool success = false;
+ if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+ {
+ uint8_t *src = data_sp->GetBytes();
+ if (src)
+ {
+ ::memcpy (&m_gpr_mips64, src, GetGPRSize());
+
+ if (WriteGPR())
+ {
+ src += GetGPRSize();
+ }
+ }
+ }
+ return success;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpoint(addr_t addr, size_t size,
+ bool read, bool write)
+{
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+ uint32_t hw_index;
+
+ for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
+ {
+ if (IsWatchpointVacant(hw_index))
+ return SetHardwareWatchpointWithIndex(addr, size,
+ read, write,
+ hw_index);
+ }
+
+ return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ClearHardwareWatchpoint(uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::HardwareSingleStep(bool enable)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::UpdateAfterBreakpoint()
+{
+ // PC points one byte past the int3 responsible for the breakpoint.
+ lldb::addr_t pc;
+
+ if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+ return false;
+
+ SetPC(pc - 1);
+ return true;
+}
+
+unsigned
+RegisterContextPOSIXProcessMonitor_mips64::GetRegisterIndexFromOffset(unsigned offset)
+{
+ unsigned reg;
+ for (reg = 0; reg < k_num_registers_mips64; reg++)
+ {
+ if (GetRegisterInfo()[reg].byte_offset == offset)
+ break;
+ }
+ assert(reg < k_num_registers_mips64 && "Invalid register offset.");
+ return reg;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointHit(uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ClearWatchpointHits()
+{
+ return false;
+}
+
+addr_t
+RegisterContextPOSIXProcessMonitor_mips64::GetWatchpointAddress(uint32_t hw_index)
+{
+ return LLDB_INVALID_ADDRESS;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointVacant(uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
+ bool read, bool write,
+ uint32_t hw_index)
+{
+ return false;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_mips64::NumSupportedHardwareWatchpoints()
+{
+ return 0;
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h
new file mode 100644
index 000000000000..8f545eef0d5e
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h
@@ -0,0 +1,95 @@
+//===-- RegisterContextPOSIXProcessMonitor_mips64.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_mips64_H_
+#define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
+
+#include "Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h"
+
+class RegisterContextPOSIXProcessMonitor_mips64:
+ public RegisterContextPOSIX_mips64,
+ public POSIXBreakpointProtocol
+{
+public:
+ RegisterContextPOSIXProcessMonitor_mips64(lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info);
+
+protected:
+ bool
+ ReadGPR();
+
+ bool
+ ReadFPR();
+
+ bool
+ WriteGPR();
+
+ bool
+ WriteFPR();
+
+ // lldb_private::RegisterContext
+ bool
+ ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
+
+ bool
+ WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value);
+
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+ uint32_t
+ SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write);
+
+ bool
+ ClearHardwareWatchpoint(uint32_t hw_index);
+
+ bool
+ HardwareSingleStep(bool enable);
+
+ // POSIXBreakpointProtocol
+ bool
+ UpdateAfterBreakpoint();
+
+ unsigned
+ GetRegisterIndexFromOffset(unsigned offset);
+
+ bool
+ IsWatchpointHit(uint32_t hw_index);
+
+ bool
+ ClearWatchpointHits();
+
+ lldb::addr_t
+ GetWatchpointAddress(uint32_t hw_index);
+
+ bool
+ IsWatchpointVacant(uint32_t hw_index);
+
+ bool
+ SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index);
+
+ uint32_t
+ NumSupportedHardwareWatchpoints();
+
+private:
+ ProcessMonitor &
+ GetMonitor();
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
new file mode 100644
index 000000000000..98e0bce68678
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
@@ -0,0 +1,634 @@
+//===-- RegisterContextPOSIXProcessMonitor_x86.h ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "lldb/Target/Thread.h"
+#include "lldb/Core/RegisterValue.h"
+
+#include "ProcessPOSIX.h"
+#include "RegisterContextPOSIXProcessMonitor_x86.h"
+#include "ProcessMonitor.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+// Support ptrace extensions even when compiled without required kernel support
+#ifndef NT_X86_XSTATE
+ #define NT_X86_XSTATE 0x202
+#endif
+
+#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(FPR))
+
+static uint32_t
+size_and_rw_bits(size_t size, bool read, bool write)
+{
+ uint32_t rw;
+
+ if (read)
+ rw = 0x3; // READ or READ/WRITE
+ else if (write)
+ rw = 0x1; // WRITE
+ else
+ assert(0 && "read and write cannot both be false");
+
+ switch (size)
+ {
+ case 1:
+ return rw;
+ case 2:
+ return (0x1 << 2) | rw;
+ case 4:
+ return (0x3 << 2) | rw;
+ case 8:
+ return (0x2 << 2) | rw;
+ default:
+ assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
+ }
+}
+
+RegisterContextPOSIXProcessMonitor_x86_64::RegisterContextPOSIXProcessMonitor_x86_64(Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info)
+ : RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info)
+{
+}
+
+ProcessMonitor &
+RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor()
+{
+ ProcessSP base = CalculateProcess();
+ ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ return process->GetMonitor();
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ReadGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ReadFPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ if (GetFPRType() == eFXSAVE)
+ return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+ if (GetFPRType() == eXSAVE)
+ return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::WriteGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::WriteFPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ if (GetFPRType() == eFXSAVE)
+ return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+ if (GetFPRType() == eXSAVE)
+ return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const unsigned reg,
+ RegisterValue &value)
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg),
+ GetRegisterName(reg),
+ GetRegisterSize(reg),
+ value);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const unsigned reg,
+ const RegisterValue &value)
+{
+ unsigned reg_to_write = reg;
+ RegisterValue value_to_write = value;
+
+ // Check if this is a subregister of a full register.
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
+ if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
+ {
+ RegisterValue full_value;
+ uint32_t full_reg = reg_info->invalidate_regs[0];
+ const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
+
+ // Read the full register.
+ if (ReadRegister(full_reg_info, full_value))
+ {
+ Error error;
+ ByteOrder byte_order = GetByteOrder();
+ uint8_t dst[RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the full register.
+ const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
+ dst,
+ sizeof(dst),
+ byte_order,
+ error);
+ if (error.Success() && dest_size)
+ {
+ uint8_t src[RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the source data.
+ const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
+ if (error.Success() && src_size && (src_size < dest_size))
+ {
+ // Copy the src bytes to the destination.
+ memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
+ // Set this full register as the value to write.
+ value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
+ value_to_write.SetType(full_reg_info);
+ reg_to_write = full_reg;
+ }
+ }
+ }
+ }
+
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg_to_write),
+ GetRegisterName(reg_to_write),
+ value_to_write);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+ if (!reg_info)
+ return false;
+
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+ if (IsFPR(reg, GetFPRType()))
+ {
+ if (!ReadFPR())
+ return false;
+ }
+ else
+ {
+ uint32_t full_reg = reg;
+ bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
+
+ if (is_subreg)
+ {
+ // Read the full aligned 64-bit register.
+ full_reg = reg_info->invalidate_regs[0];
+ }
+
+ bool success = ReadRegister(full_reg, value);
+
+ if (success)
+ {
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
+ if (is_subreg && (reg_info->byte_offset & 0x1))
+ value.SetUInt64(value.GetAsUInt64() >> 8);
+
+ // If our return byte size was greater than the return value reg size, then
+ // use the type specified by reg_info rather than the uint64_t default
+ if (value.GetByteSize() > reg_info->byte_size)
+ value.SetType(reg_info);
+ }
+ return success;
+ }
+
+ if (reg_info->encoding == eEncodingVector)
+ {
+ ByteOrder byte_order = GetByteOrder();
+
+ if (byte_order != ByteOrder::eByteOrderInvalid)
+ {
+ if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
+ value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, reg_info->byte_size, byte_order);
+ if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
+ value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, reg_info->byte_size, byte_order);
+ if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
+ value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, reg_info->byte_size, byte_order);
+ if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm)
+ {
+ // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
+ if (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order))
+ value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, reg_info->byte_size, byte_order);
+ else
+ return false;
+ }
+ return value.GetType() == RegisterValue::eTypeBytes;
+ }
+ return false;
+ }
+
+ // Get pointer to m_fpr.xstate.fxsave 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_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+ if (IsGPR(reg))
+ return WriteRegister(reg, value);
+
+ if (IsFPR(reg, GetFPRType()))
+ {
+ if (reg_info->encoding == eEncodingVector)
+ {
+ if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
+ ::memcpy (m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, value.GetBytes(), value.GetByteSize());
+
+ if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
+ ::memcpy (m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, value.GetBytes(), value.GetByteSize());
+
+ if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
+ ::memcpy (m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, value.GetBytes(), value.GetByteSize());
+
+ if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm)
+ {
+ if (GetFPRType() != eXSAVE)
+ return false; // the target processor does not support AVX
+
+ // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes
+ ::memcpy (m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, value.GetBytes(), value.GetByteSize());
+ if (false == CopyYMMtoXSTATE(reg, GetByteOrder()))
+ return false;
+ }
+ }
+ else
+ {
+ // Get pointer to m_fpr.xstate.fxsave variable and set the data to it.
+ assert (reg_info->byte_offset < sizeof(m_fpr));
+ uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset;
+ switch (reg_info->byte_size)
+ {
+ case 2:
+ *(uint16_t *)dst = value.GetAsUInt16();
+ break;
+ case 4:
+ *(uint32_t *)dst = value.GetAsUInt32();
+ break;
+ case 8:
+ *(uint64_t *)dst = value.GetAsUInt64();
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ return false;
+ }
+ }
+
+ if (WriteFPR())
+ {
+ if (IsAVX(reg))
+ return CopyYMMtoXSTATE(reg, GetByteOrder());
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp)
+{
+ bool success = false;
+ data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+ if (data_sp && ReadGPR () && ReadFPR ())
+ {
+ uint8_t *dst = data_sp->GetBytes();
+ success = dst != 0;
+
+ if (success)
+ {
+ ::memcpy (dst, &m_gpr_x86_64, GetGPRSize());
+ dst += GetGPRSize();
+ }
+ if (GetFPRType() == eFXSAVE)
+ ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+ if (GetFPRType() == eXSAVE)
+ {
+ ByteOrder byte_order = GetByteOrder();
+
+ // Assemble the YMM register content from the register halves.
+ for (uint32_t reg = m_reg_info.first_ymm; success && reg <= m_reg_info.last_ymm; ++reg)
+ success = CopyXSTATEtoYMM(reg, byte_order);
+
+ if (success)
+ {
+ // Copy the extended register state including the assembled ymm registers.
+ ::memcpy (dst, &m_fpr, sizeof(m_fpr));
+ }
+ }
+ }
+ return success;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp)
+{
+ bool success = false;
+ if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+ {
+ uint8_t *src = data_sp->GetBytes();
+ if (src)
+ {
+ ::memcpy (&m_gpr_x86_64, src, GetGPRSize());
+
+ if (WriteGPR())
+ {
+ src += GetGPRSize();
+ if (GetFPRType() == eFXSAVE)
+ ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
+ if (GetFPRType() == eXSAVE)
+ ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
+
+ success = WriteFPR();
+ if (success)
+ {
+ success = true;
+
+ if (GetFPRType() == eXSAVE)
+ {
+ ByteOrder byte_order = GetByteOrder();
+
+ // Parse the YMM register content from the register halves.
+ for (uint32_t reg = m_reg_info.first_ymm; success && reg <= m_reg_info.last_ymm; ++reg)
+ success = CopyYMMtoXSTATE(reg, byte_order);
+ }
+ }
+ }
+ }
+ }
+ return success;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpoint(addr_t addr, size_t size,
+ bool read, bool write)
+{
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+ uint32_t hw_index;
+
+ for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
+ {
+ if (IsWatchpointVacant(hw_index))
+ return SetHardwareWatchpointWithIndex(addr, size,
+ read, write,
+ hw_index);
+ }
+
+ return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ClearHardwareWatchpoint(uint32_t hw_index)
+{
+ if (hw_index < NumSupportedHardwareWatchpoints())
+ {
+ RegisterValue current_dr7_bits;
+
+ if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits))
+ {
+ uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() & ~(3 << (2*hw_index));
+
+ if (WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits)))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::HardwareSingleStep(bool enable)
+{
+ enum { TRACE_BIT = 0x100 };
+ uint64_t rflags;
+
+ if ((rflags = ReadRegisterAsUnsigned(m_reg_info.gpr_flags, -1UL)) == -1UL)
+ return false;
+
+ if (enable)
+ {
+ if (rflags & TRACE_BIT)
+ return true;
+
+ rflags |= TRACE_BIT;
+ }
+ else
+ {
+ if (!(rflags & TRACE_BIT))
+ return false;
+
+ rflags &= ~TRACE_BIT;
+ }
+
+ return WriteRegisterFromUnsigned(m_reg_info.gpr_flags, rflags);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::UpdateAfterBreakpoint()
+{
+ // PC points one byte past the int3 responsible for the breakpoint.
+ lldb::addr_t pc;
+
+ if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+ return false;
+
+ SetPC(pc - 1);
+ return true;
+}
+
+unsigned
+RegisterContextPOSIXProcessMonitor_x86_64::GetRegisterIndexFromOffset(unsigned offset)
+{
+ unsigned reg;
+ for (reg = 0; reg < m_reg_info.num_registers; reg++)
+ {
+ if (GetRegisterInfo()[reg].byte_offset == offset)
+ break;
+ }
+ assert(reg < m_reg_info.num_registers && "Invalid register offset.");
+ return reg;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointHit(uint32_t hw_index)
+{
+ bool is_hit = false;
+
+ if (m_watchpoints_initialized == false)
+ {
+ // Reset the debug status and debug control registers
+ RegisterValue zero_bits = RegisterValue(uint64_t(0));
+ if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || !WriteRegister(m_reg_info.first_dr + 7, zero_bits))
+ assert(false && "Could not initialize watchpoint registers");
+ m_watchpoints_initialized = true;
+ }
+
+ if (hw_index < NumSupportedHardwareWatchpoints())
+ {
+ RegisterValue value;
+
+ if (ReadRegister(m_reg_info.first_dr + 6, value))
+ {
+ uint64_t val = value.GetAsUInt64();
+ is_hit = val & (1 << hw_index);
+ }
+ }
+
+ return is_hit;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ClearWatchpointHits()
+{
+ return WriteRegister(m_reg_info.first_dr + 6, RegisterValue((uint64_t)0));
+}
+
+addr_t
+RegisterContextPOSIXProcessMonitor_x86_64::GetWatchpointAddress(uint32_t hw_index)
+{
+ addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS;
+
+ if (hw_index < NumSupportedHardwareWatchpoints())
+ {
+ if (!IsWatchpointVacant(hw_index))
+ {
+ RegisterValue value;
+
+ if (ReadRegister(m_reg_info.first_dr + hw_index, value))
+ wp_monitor_addr = value.GetAsUInt64();
+ }
+ }
+
+ return wp_monitor_addr;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointVacant(uint32_t hw_index)
+{
+ bool is_vacant = false;
+ RegisterValue value;
+
+ assert(hw_index < NumSupportedHardwareWatchpoints());
+
+ if (m_watchpoints_initialized == false)
+ {
+ // Reset the debug status and debug control registers
+ RegisterValue zero_bits = RegisterValue(uint64_t(0));
+ if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || !WriteRegister(m_reg_info.first_dr + 7, zero_bits))
+ assert(false && "Could not initialize watchpoint registers");
+ m_watchpoints_initialized = true;
+ }
+
+ if (ReadRegister(m_reg_info.first_dr + 7, value))
+ {
+ uint64_t val = value.GetAsUInt64();
+ is_vacant = (val & (3 << 2*hw_index)) == 0;
+ }
+
+ return is_vacant;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
+ bool read, bool write,
+ uint32_t hw_index)
+{
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+
+ if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints)
+ return false;
+
+ if (!(size == 1 || size == 2 || size == 4 || size == 8))
+ return false;
+
+ if (read == false && write == false)
+ return false;
+
+ if (!IsWatchpointVacant(hw_index))
+ return false;
+
+ // Set both dr7 (debug control register) and dri (debug address register).
+
+ // dr7{7-0} encodes the local/global enable bits:
+ // global enable --. .-- local enable
+ // | |
+ // v v
+ // dr0 -> bits{1-0}
+ // dr1 -> bits{3-2}
+ // dr2 -> bits{5-4}
+ // dr3 -> bits{7-6}
+ //
+ // dr7{31-16} encodes the rw/len bits:
+ // b_x+3, b_x+2, b_x+1, b_x
+ // where bits{x+1, x} => rw
+ // 0b00: execute, 0b01: write, 0b11: read-or-write,
+ // 0b10: io read-or-write (unused)
+ // and bits{x+3, x+2} => len
+ // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
+ //
+ // dr0 -> bits{19-16}
+ // dr1 -> bits{23-20}
+ // dr2 -> bits{27-24}
+ // dr3 -> bits{31-28}
+ if (hw_index < num_hw_watchpoints)
+ {
+ RegisterValue current_dr7_bits;
+
+ if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits))
+ {
+ uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() |
+ (1 << (2*hw_index) |
+ size_and_rw_bits(size, read, write) <<
+ (16+4*hw_index));
+
+ if (WriteRegister(m_reg_info.first_dr + hw_index, RegisterValue(addr)) &&
+ WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits)))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_x86_64::NumSupportedHardwareWatchpoints()
+{
+ // Available debug address registers: dr0, dr1, dr2, dr3
+ return 4;
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h
new file mode 100644
index 000000000000..2b64fa8003a2
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h
@@ -0,0 +1,95 @@
+//===-- RegisterContextPOSIXProcessMonitor_x86.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_x86_H_
+#define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
+
+#include "Plugins/Process/POSIX/RegisterContextPOSIX_x86.h"
+
+class RegisterContextPOSIXProcessMonitor_x86_64:
+ public RegisterContextPOSIX_x86,
+ public POSIXBreakpointProtocol
+{
+public:
+ RegisterContextPOSIXProcessMonitor_x86_64(lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ 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/RegisterContextPOSIX_mips64.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp
new file mode 100644
index 000000000000..45c99aec1657
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp
@@ -0,0 +1,238 @@
+//===-- RegisterContextPOSIX_mips64.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 "ProcessPOSIX.h"
+#include "RegisterContextPOSIX_mips64.h"
+#include "Plugins/Process/elf-core/ProcessElfCore.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+static const
+uint32_t g_gpr_regnums[] =
+{
+ gpr_zero_mips64,
+ gpr_r1_mips64,
+ gpr_r2_mips64,
+ gpr_r3_mips64,
+ gpr_r4_mips64,
+ gpr_r5_mips64,
+ gpr_r6_mips64,
+ gpr_r7_mips64,
+ gpr_r8_mips64,
+ gpr_r9_mips64,
+ gpr_r10_mips64,
+ gpr_r11_mips64,
+ gpr_r12_mips64,
+ gpr_r13_mips64,
+ gpr_r14_mips64,
+ gpr_r15_mips64,
+ gpr_r16_mips64,
+ gpr_r17_mips64,
+ gpr_r18_mips64,
+ gpr_r19_mips64,
+ gpr_r20_mips64,
+ gpr_r21_mips64,
+ gpr_r22_mips64,
+ gpr_r23_mips64,
+ gpr_r24_mips64,
+ gpr_r25_mips64,
+ gpr_r26_mips64,
+ gpr_r27_mips64,
+ gpr_gp_mips64,
+ gpr_sp_mips64,
+ gpr_r30_mips64,
+ gpr_ra_mips64,
+ gpr_sr_mips64,
+ gpr_mullo_mips64,
+ gpr_mulhi_mips64,
+ gpr_badvaddr_mips64,
+ gpr_cause_mips64,
+ gpr_pc_mips64,
+ gpr_ic_mips64,
+ gpr_dummy_mips64
+};
+
+// Number of register sets provided by this context.
+enum
+{
+ k_num_register_sets = 1
+};
+
+static const RegisterSet
+g_reg_sets_mips64[k_num_register_sets] =
+{
+ { "General Purpose Registers", "gpr", k_num_gpr_registers_mips64, g_gpr_regnums },
+};
+
+bool RegisterContextPOSIX_mips64::IsGPR(unsigned reg)
+{
+ return reg <= k_num_gpr_registers_mips64; // GPR's come first.
+}
+
+bool
+RegisterContextPOSIX_mips64::IsFPR(unsigned reg)
+{
+ // XXX
+ return false;
+}
+
+RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64(Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info)
+ : RegisterContext(thread, concrete_frame_idx)
+{
+ m_register_info_ap.reset(register_info);
+
+ // elf-core yet to support ReadFPR()
+ ProcessSP base = CalculateProcess();
+ if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
+ return;
+}
+
+RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64()
+{
+}
+
+void
+RegisterContextPOSIX_mips64::Invalidate()
+{
+}
+
+void
+RegisterContextPOSIX_mips64::InvalidateAllRegisters()
+{
+}
+
+unsigned
+RegisterContextPOSIX_mips64::GetRegisterOffset(unsigned reg)
+{
+ assert(reg < k_num_registers_mips64 && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_offset;
+}
+
+unsigned
+RegisterContextPOSIX_mips64::GetRegisterSize(unsigned reg)
+{
+ assert(reg < k_num_registers_mips64 && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_size;
+}
+
+size_t
+RegisterContextPOSIX_mips64::GetRegisterCount()
+{
+ size_t num_registers = k_num_registers_mips64;
+ return num_registers;
+}
+
+size_t
+RegisterContextPOSIX_mips64::GetGPRSize()
+{
+ return m_register_info_ap->GetGPRSize();
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_mips64::GetRegisterInfo()
+{
+ // Commonly, this method is overridden and g_register_infos is copied and specialized.
+ // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ return m_register_info_ap->GetRegisterInfo ();
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_mips64::GetRegisterInfoAtIndex(size_t reg)
+{
+ if (reg < k_num_registers_mips64)
+ return &GetRegisterInfo()[reg];
+ else
+ return NULL;
+}
+
+size_t
+RegisterContextPOSIX_mips64::GetRegisterSetCount()
+{
+ size_t sets = 0;
+ for (size_t set = 0; set < k_num_register_sets; ++set)
+ {
+ if (IsRegisterSetAvailable(set))
+ ++sets;
+ }
+
+ return sets;
+}
+
+const RegisterSet *
+RegisterContextPOSIX_mips64::GetRegisterSet(size_t set)
+{
+ if (IsRegisterSetAvailable(set))
+ return &g_reg_sets_mips64[set];
+ else
+ return NULL;
+}
+
+const char *
+RegisterContextPOSIX_mips64::GetRegisterName(unsigned reg)
+{
+ assert(reg < k_num_registers_mips64 && "Invalid register offset.");
+ return GetRegisterInfo()[reg].name;
+}
+
+lldb::ByteOrder
+RegisterContextPOSIX_mips64::GetByteOrder()
+{
+ // Get the target process whose privileged thread was used for the register read.
+ lldb::ByteOrder byte_order = eByteOrderInvalid;
+ Process *process = CalculateProcess().get();
+
+ if (process)
+ byte_order = process->GetByteOrder();
+ return byte_order;
+}
+
+bool
+RegisterContextPOSIX_mips64::IsRegisterSetAvailable(size_t set_index)
+{
+ size_t num_sets = k_num_register_sets;
+
+ return (set_index < num_sets);
+}
+
+// Used when parsing DWARF and EH frame information and any other
+// object file sections that contain register numbers in them.
+uint32_t
+RegisterContextPOSIX_mips64::ConvertRegisterKindToRegisterNumber(uint32_t kind,
+ uint32_t num)
+{
+ const uint32_t num_regs = GetRegisterCount();
+
+ assert (kind < kNumRegisterKinds);
+ for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx)
+ {
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx);
+
+ if (reg_info->kinds[kind] == num)
+ return reg_idx;
+ }
+
+ return LLDB_INVALID_REGNUM;
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h b/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h
new file mode 100644
index 000000000000..a2a7d1f45271
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h
@@ -0,0 +1,138 @@
+//===-- RegisterContextPOSIX_mips64.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_mips64_H_
+#define liblldb_RegisterContextPOSIX_mips64_H_
+
+#include "lldb/Core/Log.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterContext_mips64.h"
+
+class ProcessMonitor;
+
+// ---------------------------------------------------------------------------
+// Internal codes for all mips64 registers.
+// ---------------------------------------------------------------------------
+enum
+{
+ k_first_gpr_mips64,
+ gpr_zero_mips64 = k_first_gpr_mips64,
+ gpr_r1_mips64,
+ gpr_r2_mips64,
+ gpr_r3_mips64,
+ gpr_r4_mips64,
+ gpr_r5_mips64,
+ gpr_r6_mips64,
+ gpr_r7_mips64,
+ gpr_r8_mips64,
+ gpr_r9_mips64,
+ gpr_r10_mips64,
+ gpr_r11_mips64,
+ gpr_r12_mips64,
+ gpr_r13_mips64,
+ gpr_r14_mips64,
+ gpr_r15_mips64,
+ gpr_r16_mips64,
+ gpr_r17_mips64,
+ gpr_r18_mips64,
+ gpr_r19_mips64,
+ gpr_r20_mips64,
+ gpr_r21_mips64,
+ gpr_r22_mips64,
+ gpr_r23_mips64,
+ gpr_r24_mips64,
+ gpr_r25_mips64,
+ gpr_r26_mips64,
+ gpr_r27_mips64,
+ gpr_gp_mips64,
+ gpr_sp_mips64,
+ gpr_r30_mips64,
+ gpr_ra_mips64,
+ gpr_sr_mips64,
+ gpr_mullo_mips64,
+ gpr_mulhi_mips64,
+ gpr_badvaddr_mips64,
+ gpr_cause_mips64,
+ gpr_pc_mips64,
+ gpr_ic_mips64,
+ gpr_dummy_mips64,
+
+ k_num_registers_mips64,
+ k_num_gpr_registers_mips64 = k_num_registers_mips64
+};
+
+class RegisterContextPOSIX_mips64
+ : public lldb_private::RegisterContext
+{
+public:
+ RegisterContextPOSIX_mips64 (lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info);
+
+ ~RegisterContextPOSIX_mips64();
+
+ 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(uint32_t 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)
+
+ // 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_mips64_H_
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp
new file mode 100644
index 000000000000..9ae541a6309b
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp
@@ -0,0 +1,666 @@
+//===-- RegisterContextPOSIX_x86.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 "ProcessPOSIX.h"
+#include "RegisterContext_x86.h"
+#include "RegisterContextPOSIX_x86.h"
+#include "Plugins/Process/elf-core/ProcessElfCore.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+const uint32_t
+g_gpr_regnums_i386[] =
+{
+ gpr_eax_i386,
+ gpr_ebx_i386,
+ gpr_ecx_i386,
+ gpr_edx_i386,
+ gpr_edi_i386,
+ gpr_esi_i386,
+ gpr_ebp_i386,
+ gpr_esp_i386,
+ gpr_eip_i386,
+ gpr_eflags_i386,
+ gpr_cs_i386,
+ gpr_fs_i386,
+ gpr_gs_i386,
+ gpr_ss_i386,
+ gpr_ds_i386,
+ gpr_es_i386,
+ gpr_ax_i386,
+ gpr_bx_i386,
+ gpr_cx_i386,
+ gpr_dx_i386,
+ gpr_di_i386,
+ gpr_si_i386,
+ gpr_bp_i386,
+ gpr_sp_i386,
+ gpr_ah_i386,
+ gpr_bh_i386,
+ gpr_ch_i386,
+ gpr_dh_i386,
+ gpr_al_i386,
+ gpr_bl_i386,
+ gpr_cl_i386,
+ gpr_dl_i386
+};
+static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) == k_num_gpr_registers_i386,
+ "g_gpr_regnums_i386 has wrong number of register infos");
+
+const uint32_t
+g_fpu_regnums_i386[] =
+{
+ fpu_fctrl_i386,
+ fpu_fstat_i386,
+ fpu_ftag_i386,
+ fpu_fop_i386,
+ fpu_fiseg_i386,
+ fpu_fioff_i386,
+ fpu_foseg_i386,
+ fpu_fooff_i386,
+ fpu_mxcsr_i386,
+ fpu_mxcsrmask_i386,
+ fpu_st0_i386,
+ fpu_st1_i386,
+ fpu_st2_i386,
+ fpu_st3_i386,
+ fpu_st4_i386,
+ fpu_st5_i386,
+ fpu_st6_i386,
+ fpu_st7_i386,
+ fpu_mm0_i386,
+ fpu_mm1_i386,
+ fpu_mm2_i386,
+ fpu_mm3_i386,
+ fpu_mm4_i386,
+ fpu_mm5_i386,
+ fpu_mm6_i386,
+ fpu_mm7_i386,
+ fpu_xmm0_i386,
+ fpu_xmm1_i386,
+ fpu_xmm2_i386,
+ fpu_xmm3_i386,
+ fpu_xmm4_i386,
+ fpu_xmm5_i386,
+ fpu_xmm6_i386,
+ fpu_xmm7_i386
+};
+static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) == k_num_fpr_registers_i386,
+ "g_fpu_regnums_i386 has wrong number of register infos");
+
+const uint32_t
+g_avx_regnums_i386[] =
+{
+ fpu_ymm0_i386,
+ fpu_ymm1_i386,
+ fpu_ymm2_i386,
+ fpu_ymm3_i386,
+ fpu_ymm4_i386,
+ fpu_ymm5_i386,
+ fpu_ymm6_i386,
+ fpu_ymm7_i386
+};
+static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) == k_num_avx_registers_i386,
+ " g_avx_regnums_i386 has wrong number of register infos");
+
+static const
+uint32_t g_gpr_regnums_x86_64[] =
+{
+ gpr_rax_x86_64,
+ gpr_rbx_x86_64,
+ gpr_rcx_x86_64,
+ gpr_rdx_x86_64,
+ gpr_rdi_x86_64,
+ gpr_rsi_x86_64,
+ gpr_rbp_x86_64,
+ gpr_rsp_x86_64,
+ gpr_r8_x86_64,
+ gpr_r9_x86_64,
+ gpr_r10_x86_64,
+ gpr_r11_x86_64,
+ gpr_r12_x86_64,
+ gpr_r13_x86_64,
+ gpr_r14_x86_64,
+ gpr_r15_x86_64,
+ gpr_rip_x86_64,
+ gpr_rflags_x86_64,
+ gpr_cs_x86_64,
+ gpr_fs_x86_64,
+ gpr_gs_x86_64,
+ gpr_ss_x86_64,
+ gpr_ds_x86_64,
+ gpr_es_x86_64,
+ gpr_eax_x86_64,
+ gpr_ebx_x86_64,
+ gpr_ecx_x86_64,
+ gpr_edx_x86_64,
+ gpr_edi_x86_64,
+ gpr_esi_x86_64,
+ gpr_ebp_x86_64,
+ gpr_esp_x86_64,
+ gpr_r8d_x86_64, // Low 32 bits or r8
+ gpr_r9d_x86_64, // Low 32 bits or r9
+ gpr_r10d_x86_64, // Low 32 bits or r10
+ gpr_r11d_x86_64, // Low 32 bits or r11
+ gpr_r12d_x86_64, // Low 32 bits or r12
+ gpr_r13d_x86_64, // Low 32 bits or r13
+ gpr_r14d_x86_64, // Low 32 bits or r14
+ gpr_r15d_x86_64, // Low 32 bits or r15
+ gpr_ax_x86_64,
+ gpr_bx_x86_64,
+ gpr_cx_x86_64,
+ gpr_dx_x86_64,
+ gpr_di_x86_64,
+ gpr_si_x86_64,
+ gpr_bp_x86_64,
+ gpr_sp_x86_64,
+ gpr_r8w_x86_64, // Low 16 bits or r8
+ gpr_r9w_x86_64, // Low 16 bits or r9
+ gpr_r10w_x86_64, // Low 16 bits or r10
+ gpr_r11w_x86_64, // Low 16 bits or r11
+ gpr_r12w_x86_64, // Low 16 bits or r12
+ gpr_r13w_x86_64, // Low 16 bits or r13
+ gpr_r14w_x86_64, // Low 16 bits or r14
+ gpr_r15w_x86_64, // Low 16 bits or r15
+ gpr_ah_x86_64,
+ gpr_bh_x86_64,
+ gpr_ch_x86_64,
+ gpr_dh_x86_64,
+ gpr_al_x86_64,
+ gpr_bl_x86_64,
+ gpr_cl_x86_64,
+ gpr_dl_x86_64,
+ gpr_dil_x86_64,
+ gpr_sil_x86_64,
+ gpr_bpl_x86_64,
+ gpr_spl_x86_64,
+ gpr_r8l_x86_64, // Low 8 bits or r8
+ gpr_r9l_x86_64, // Low 8 bits or r9
+ gpr_r10l_x86_64, // Low 8 bits or r10
+ gpr_r11l_x86_64, // Low 8 bits or r11
+ gpr_r12l_x86_64, // Low 8 bits or r12
+ gpr_r13l_x86_64, // Low 8 bits or r13
+ gpr_r14l_x86_64, // Low 8 bits or r14
+ gpr_r15l_x86_64, // Low 8 bits or r15
+};
+static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) == k_num_gpr_registers_x86_64,
+ "g_gpr_regnums_x86_64 has wrong number of register infos");
+
+static const uint32_t
+g_fpu_regnums_x86_64[] =
+{
+ fpu_fctrl_x86_64,
+ fpu_fstat_x86_64,
+ fpu_ftag_x86_64,
+ fpu_fop_x86_64,
+ fpu_fiseg_x86_64,
+ fpu_fioff_x86_64,
+ fpu_foseg_x86_64,
+ fpu_fooff_x86_64,
+ fpu_mxcsr_x86_64,
+ fpu_mxcsrmask_x86_64,
+ fpu_st0_x86_64,
+ fpu_st1_x86_64,
+ fpu_st2_x86_64,
+ fpu_st3_x86_64,
+ fpu_st4_x86_64,
+ fpu_st5_x86_64,
+ fpu_st6_x86_64,
+ fpu_st7_x86_64,
+ fpu_mm0_x86_64,
+ fpu_mm1_x86_64,
+ fpu_mm2_x86_64,
+ fpu_mm3_x86_64,
+ fpu_mm4_x86_64,
+ fpu_mm5_x86_64,
+ fpu_mm6_x86_64,
+ fpu_mm7_x86_64,
+ fpu_xmm0_x86_64,
+ fpu_xmm1_x86_64,
+ fpu_xmm2_x86_64,
+ fpu_xmm3_x86_64,
+ fpu_xmm4_x86_64,
+ fpu_xmm5_x86_64,
+ fpu_xmm6_x86_64,
+ fpu_xmm7_x86_64,
+ fpu_xmm8_x86_64,
+ fpu_xmm9_x86_64,
+ fpu_xmm10_x86_64,
+ fpu_xmm11_x86_64,
+ fpu_xmm12_x86_64,
+ fpu_xmm13_x86_64,
+ fpu_xmm14_x86_64,
+ fpu_xmm15_x86_64
+};
+static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) == k_num_fpr_registers_x86_64,
+ "g_fpu_regnums_x86_64 has wrong number of register infos");
+
+static const uint32_t
+g_avx_regnums_x86_64[] =
+{
+ fpu_ymm0_x86_64,
+ fpu_ymm1_x86_64,
+ fpu_ymm2_x86_64,
+ fpu_ymm3_x86_64,
+ fpu_ymm4_x86_64,
+ fpu_ymm5_x86_64,
+ fpu_ymm6_x86_64,
+ fpu_ymm7_x86_64,
+ fpu_ymm8_x86_64,
+ fpu_ymm9_x86_64,
+ fpu_ymm10_x86_64,
+ fpu_ymm11_x86_64,
+ fpu_ymm12_x86_64,
+ fpu_ymm13_x86_64,
+ fpu_ymm14_x86_64,
+ fpu_ymm15_x86_64
+};
+static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) == k_num_avx_registers_x86_64,
+ "g_avx_regnums_x86_64 has wrong number of register infos");
+
+uint32_t RegisterContextPOSIX_x86::g_contained_eax[] = { gpr_eax_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_ebx[] = { gpr_ebx_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_ecx[] = { gpr_ecx_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_edx[] = { gpr_edx_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_edi[] = { gpr_edi_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_esi[] = { gpr_esi_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_ebp[] = { gpr_ebp_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_esp[] = { gpr_esp_i386, LLDB_INVALID_REGNUM };
+
+uint32_t RegisterContextPOSIX_x86::g_invalidate_eax[] = { gpr_eax_i386, gpr_ax_i386, gpr_ah_i386, gpr_al_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_ebx[] = { gpr_ebx_i386, gpr_bx_i386, gpr_bh_i386, gpr_bl_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_ecx[] = { gpr_ecx_i386, gpr_cx_i386, gpr_ch_i386, gpr_cl_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_edx[] = { gpr_edx_i386, gpr_dx_i386, gpr_dh_i386, gpr_dl_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_edi[] = { gpr_edi_i386, gpr_di_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_esi[] = { gpr_esi_i386, gpr_si_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_ebp[] = { gpr_ebp_i386, gpr_bp_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_esp[] = { gpr_esp_i386, gpr_sp_i386, LLDB_INVALID_REGNUM };
+
+uint32_t RegisterContextPOSIX_x86::g_contained_rax[] = { gpr_rax_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rbx[] = { gpr_rbx_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rcx[] = { gpr_rcx_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rdx[] = { gpr_rdx_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rdi[] = { gpr_rdi_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rsi[] = { gpr_rsi_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rbp[] = { gpr_rbp_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rsp[] = { gpr_rsp_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r8[] = { gpr_r8_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r9[] = { gpr_r9_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r10[] = { gpr_r10_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r11[] = { gpr_r11_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r12[] = { gpr_r12_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r13[] = { gpr_r13_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r14[] = { gpr_r14_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r15[] = { gpr_r15_x86_64, LLDB_INVALID_REGNUM };
+
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rax[] = { gpr_rax_x86_64, gpr_eax_x86_64, gpr_ax_x86_64, gpr_ah_x86_64, gpr_al_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rbx[] = { gpr_rbx_x86_64, gpr_ebx_x86_64, gpr_bx_x86_64, gpr_bh_x86_64, gpr_bl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rcx[] = { gpr_rcx_x86_64, gpr_ecx_x86_64, gpr_cx_x86_64, gpr_ch_x86_64, gpr_cl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rdx[] = { gpr_rdx_x86_64, gpr_edx_x86_64, gpr_dx_x86_64, gpr_dh_x86_64, gpr_dl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rdi[] = { gpr_rdi_x86_64, gpr_edi_x86_64, gpr_di_x86_64, gpr_dil_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rsi[] = { gpr_rsi_x86_64, gpr_esi_x86_64, gpr_si_x86_64, gpr_sil_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rbp[] = { gpr_rbp_x86_64, gpr_ebp_x86_64, gpr_bp_x86_64, gpr_bpl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rsp[] = { gpr_rsp_x86_64, gpr_esp_x86_64, gpr_sp_x86_64, gpr_spl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r8[] = { gpr_r8_x86_64, gpr_r8d_x86_64, gpr_r8w_x86_64, gpr_r8l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r9[] = { gpr_r9_x86_64, gpr_r9d_x86_64, gpr_r9w_x86_64, gpr_r9l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r10[] = { gpr_r10_x86_64, gpr_r10d_x86_64, gpr_r10w_x86_64, gpr_r10l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r11[] = { gpr_r11_x86_64, gpr_r11d_x86_64, gpr_r11w_x86_64, gpr_r11l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r12[] = { gpr_r12_x86_64, gpr_r12d_x86_64, gpr_r12w_x86_64, gpr_r12l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r13[] = { gpr_r13_x86_64, gpr_r13d_x86_64, gpr_r13w_x86_64, gpr_r13l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r14[] = { gpr_r14_x86_64, gpr_r14d_x86_64, gpr_r14w_x86_64, gpr_r14l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r15[] = { gpr_r15_x86_64, gpr_r15d_x86_64, gpr_r15w_x86_64, gpr_r15l_x86_64, LLDB_INVALID_REGNUM };
+
+// Number of register sets provided by this context.
+enum
+{
+ k_num_extended_register_sets = 1,
+ k_num_register_sets = 3
+};
+
+static const RegisterSet
+g_reg_sets_i386[k_num_register_sets] =
+{
+ { "General Purpose Registers", "gpr", k_num_gpr_registers_i386, g_gpr_regnums_i386 },
+ { "Floating Point Registers", "fpu", k_num_fpr_registers_i386, g_fpu_regnums_i386 },
+ { "Advanced Vector Extensions", "avx", k_num_avx_registers_i386, g_avx_regnums_i386 }
+};
+
+static const RegisterSet
+g_reg_sets_x86_64[k_num_register_sets] =
+{
+ { "General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, g_gpr_regnums_x86_64 },
+ { "Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, g_fpu_regnums_x86_64 },
+ { "Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, g_avx_regnums_x86_64 }
+};
+
+bool RegisterContextPOSIX_x86::IsGPR(unsigned reg)
+{
+ return reg <= m_reg_info.last_gpr; // GPR's come first.
+}
+
+bool RegisterContextPOSIX_x86::IsFPR(unsigned reg)
+{
+ return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
+}
+
+bool RegisterContextPOSIX_x86::IsAVX(unsigned reg)
+{
+ return (m_reg_info.first_ymm <= reg && reg <= m_reg_info.last_ymm);
+}
+
+bool RegisterContextPOSIX_x86::IsFPR(unsigned reg, FPRType fpr_type)
+{
+ bool generic_fpr = IsFPR(reg);
+
+ if (fpr_type == eXSAVE)
+ return generic_fpr || IsAVX(reg);
+ return generic_fpr;
+}
+
+RegisterContextPOSIX_x86::RegisterContextPOSIX_x86(Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info)
+ : RegisterContext(thread, concrete_frame_idx)
+{
+ m_register_info_ap.reset(register_info);
+
+ switch (register_info->m_target_arch.GetCore())
+ {
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ 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;
+ m_reg_info.num_avx_registers = k_num_avx_registers_i386;
+ m_reg_info.last_gpr = k_last_gpr_i386;
+ m_reg_info.first_fpr = k_first_fpr_i386;
+ m_reg_info.last_fpr = k_last_fpr_i386;
+ m_reg_info.first_st = fpu_st0_i386;
+ m_reg_info.last_st = fpu_st7_i386;
+ m_reg_info.first_mm = fpu_mm0_i386;
+ m_reg_info.last_mm = fpu_mm7_i386;
+ m_reg_info.first_xmm = fpu_xmm0_i386;
+ m_reg_info.last_xmm = fpu_xmm7_i386;
+ m_reg_info.first_ymm = fpu_ymm0_i386;
+ m_reg_info.last_ymm = fpu_ymm7_i386;
+ m_reg_info.first_dr = dr0_i386;
+ m_reg_info.gpr_flags = gpr_eflags_i386;
+ break;
+ case ArchSpec::eCore_x86_64_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;
+ m_reg_info.num_avx_registers = k_num_avx_registers_x86_64;
+ m_reg_info.last_gpr = k_last_gpr_x86_64;
+ m_reg_info.first_fpr = k_first_fpr_x86_64;
+ m_reg_info.last_fpr = k_last_fpr_x86_64;
+ m_reg_info.first_st = fpu_st0_x86_64;
+ m_reg_info.last_st = fpu_st7_x86_64;
+ m_reg_info.first_mm = fpu_mm0_x86_64;
+ m_reg_info.last_mm = fpu_mm7_x86_64;
+ m_reg_info.first_xmm = fpu_xmm0_x86_64;
+ m_reg_info.last_xmm = fpu_xmm15_x86_64;
+ m_reg_info.first_ymm = fpu_ymm0_x86_64;
+ m_reg_info.last_ymm = fpu_ymm15_x86_64;
+ m_reg_info.first_dr = dr0_x86_64;
+ m_reg_info.gpr_flags = gpr_rflags_x86_64;
+ break;
+ default:
+ assert(false && "Unhandled target architecture.");
+ break;
+ }
+
+ // Initialize m_iovec to point to the buffer and buffer size
+ // using the conventions of Berkeley style UIO structures, as required
+ // by PTRACE extensions.
+ m_iovec.iov_base = &m_fpr.xstate.xsave;
+ m_iovec.iov_len = sizeof(m_fpr.xstate.xsave);
+
+ ::memset(&m_fpr, 0, sizeof(FPR));
+
+ // elf-core yet to support ReadFPR()
+ ProcessSP base = CalculateProcess();
+ if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
+ return;
+
+ m_fpr_type = eNotValid;
+}
+
+RegisterContextPOSIX_x86::~RegisterContextPOSIX_x86()
+{
+}
+
+RegisterContextPOSIX_x86::FPRType RegisterContextPOSIX_x86::GetFPRType()
+{
+ if (m_fpr_type == eNotValid)
+ {
+ // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx
+ m_fpr_type = eXSAVE; // extended floating-point registers, if available
+ if (false == ReadFPR())
+ m_fpr_type = eFXSAVE; // assume generic floating-point registers
+ }
+ return m_fpr_type;
+}
+
+void
+RegisterContextPOSIX_x86::Invalidate()
+{
+}
+
+void
+RegisterContextPOSIX_x86::InvalidateAllRegisters()
+{
+}
+
+unsigned
+RegisterContextPOSIX_x86::GetRegisterOffset(unsigned reg)
+{
+ assert(reg < m_reg_info.num_registers && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_offset;
+}
+
+unsigned
+RegisterContextPOSIX_x86::GetRegisterSize(unsigned reg)
+{
+ assert(reg < m_reg_info.num_registers && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_size;
+}
+
+size_t
+RegisterContextPOSIX_x86::GetRegisterCount()
+{
+ size_t num_registers = m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers;
+ if (GetFPRType() == eXSAVE)
+ return num_registers + m_reg_info.num_avx_registers;
+ return num_registers;
+}
+
+size_t
+RegisterContextPOSIX_x86::GetGPRSize()
+{
+ return m_register_info_ap->GetGPRSize ();
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_x86::GetRegisterInfo()
+{
+ // Commonly, this method is overridden and g_register_infos is copied and specialized.
+ // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ return m_register_info_ap->GetRegisterInfo ();
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_x86::GetRegisterInfoAtIndex(size_t reg)
+{
+ if (reg < m_reg_info.num_registers)
+ return &GetRegisterInfo()[reg];
+ else
+ return NULL;
+}
+
+size_t
+RegisterContextPOSIX_x86::GetRegisterSetCount()
+{
+ size_t sets = 0;
+ for (size_t set = 0; set < k_num_register_sets; ++set)
+ {
+ if (IsRegisterSetAvailable(set))
+ ++sets;
+ }
+
+ return sets;
+}
+
+const RegisterSet *
+RegisterContextPOSIX_x86::GetRegisterSet(size_t set)
+{
+ if (IsRegisterSetAvailable(set))
+ {
+ switch (m_register_info_ap->m_target_arch.GetCore())
+ {
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ return &g_reg_sets_i386[set];
+ case ArchSpec::eCore_x86_64_x86_64:
+ return &g_reg_sets_x86_64[set];
+ default:
+ assert(false && "Unhandled target architecture.");
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+const char *
+RegisterContextPOSIX_x86::GetRegisterName(unsigned reg)
+{
+ assert(reg < m_reg_info.num_registers && "Invalid register offset.");
+ return GetRegisterInfo()[reg].name;
+}
+
+lldb::ByteOrder
+RegisterContextPOSIX_x86::GetByteOrder()
+{
+ // Get the target process whose privileged thread was used for the register read.
+ lldb::ByteOrder byte_order = eByteOrderInvalid;
+ Process *process = CalculateProcess().get();
+
+ if (process)
+ byte_order = process->GetByteOrder();
+ return byte_order;
+}
+
+// Parse ymm registers and into xmm.bytes and ymmh.bytes.
+bool RegisterContextPOSIX_x86::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order)
+{
+ if (!IsAVX(reg))
+ return false;
+
+ if (byte_order == eByteOrderLittle)
+ {
+ ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
+ m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
+ sizeof(XMMReg));
+ ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
+ m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
+ sizeof(YMMHReg));
+ return true;
+ }
+
+ if (byte_order == eByteOrderBig)
+ {
+ ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
+ m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
+ sizeof(XMMReg));
+ ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
+ m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
+ sizeof(YMMHReg));
+ return true;
+ }
+ return false; // unsupported or invalid byte order
+}
+
+// Concatenate xmm.bytes with ymmh.bytes
+bool RegisterContextPOSIX_x86::CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order)
+{
+ if (!IsAVX(reg))
+ return false;
+
+ if (byte_order == eByteOrderLittle)
+ {
+ ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
+ m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
+ sizeof(XMMReg));
+ ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
+ m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
+ sizeof(YMMHReg));
+ return true;
+ }
+
+ if (byte_order == eByteOrderBig)
+ {
+ ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
+ m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
+ sizeof(XMMReg));
+ ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
+ m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
+ sizeof(YMMHReg));
+ return true;
+ }
+ return false; // unsupported or invalid byte order
+}
+
+bool
+RegisterContextPOSIX_x86::IsRegisterSetAvailable(size_t set_index)
+{
+ // Note: Extended register sets are assumed to be at the end of g_reg_sets...
+ size_t num_sets = k_num_register_sets - k_num_extended_register_sets;
+
+ if (GetFPRType() == eXSAVE) // ...and to start with AVX registers.
+ ++num_sets;
+ return (set_index < num_sets);
+}
+
+
+// Used when parsing DWARF and EH frame information and any other
+// object file sections that contain register numbers in them.
+uint32_t
+RegisterContextPOSIX_x86::ConvertRegisterKindToRegisterNumber(uint32_t kind,
+ uint32_t num)
+{
+ const uint32_t num_regs = GetRegisterCount();
+
+ assert (kind < kNumRegisterKinds);
+ for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx)
+ {
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx);
+
+ if (reg_info->kinds[kind] == num)
+ return reg_idx;
+ }
+
+ return LLDB_INVALID_REGNUM;
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h b/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h
new file mode 100644
index 000000000000..5e922025b830
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h
@@ -0,0 +1,462 @@
+//===-- RegisterContextPOSIX_x86.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_x86_H_
+#define liblldb_RegisterContextPOSIX_x86_H_
+
+#include "lldb/Core/Log.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterContext_x86.h"
+
+class ProcessMonitor;
+
+//---------------------------------------------------------------------------
+// Internal codes for all i386 registers.
+//---------------------------------------------------------------------------
+enum
+{
+ k_first_gpr_i386,
+ gpr_eax_i386 = k_first_gpr_i386,
+ gpr_ebx_i386,
+ gpr_ecx_i386,
+ gpr_edx_i386,
+ gpr_edi_i386,
+ gpr_esi_i386,
+ gpr_ebp_i386,
+ gpr_esp_i386,
+ gpr_eip_i386,
+ gpr_eflags_i386,
+ gpr_cs_i386,
+ gpr_fs_i386,
+ gpr_gs_i386,
+ gpr_ss_i386,
+ gpr_ds_i386,
+ gpr_es_i386,
+
+ k_first_alias_i386,
+ gpr_ax_i386 = k_first_alias_i386,
+ gpr_bx_i386,
+ gpr_cx_i386,
+ gpr_dx_i386,
+ gpr_di_i386,
+ gpr_si_i386,
+ gpr_bp_i386,
+ gpr_sp_i386,
+ gpr_ah_i386,
+ gpr_bh_i386,
+ gpr_ch_i386,
+ gpr_dh_i386,
+ gpr_al_i386,
+ gpr_bl_i386,
+ gpr_cl_i386,
+ gpr_dl_i386,
+ k_last_alias_i386 = gpr_dl_i386,
+
+ k_last_gpr_i386 = k_last_alias_i386,
+
+ k_first_fpr_i386,
+ fpu_fctrl_i386 = k_first_fpr_i386,
+ fpu_fstat_i386,
+ fpu_ftag_i386,
+ fpu_fop_i386,
+ fpu_fiseg_i386,
+ fpu_fioff_i386,
+ fpu_foseg_i386,
+ fpu_fooff_i386,
+ fpu_mxcsr_i386,
+ fpu_mxcsrmask_i386,
+ fpu_st0_i386,
+ fpu_st1_i386,
+ fpu_st2_i386,
+ fpu_st3_i386,
+ fpu_st4_i386,
+ fpu_st5_i386,
+ fpu_st6_i386,
+ fpu_st7_i386,
+ fpu_mm0_i386,
+ fpu_mm1_i386,
+ fpu_mm2_i386,
+ fpu_mm3_i386,
+ fpu_mm4_i386,
+ fpu_mm5_i386,
+ fpu_mm6_i386,
+ fpu_mm7_i386,
+ fpu_xmm0_i386,
+ fpu_xmm1_i386,
+ fpu_xmm2_i386,
+ fpu_xmm3_i386,
+ fpu_xmm4_i386,
+ fpu_xmm5_i386,
+ fpu_xmm6_i386,
+ fpu_xmm7_i386,
+ k_last_fpr_i386 = fpu_xmm7_i386,
+
+ k_first_avx_i386,
+ fpu_ymm0_i386 = k_first_avx_i386,
+ fpu_ymm1_i386,
+ fpu_ymm2_i386,
+ fpu_ymm3_i386,
+ fpu_ymm4_i386,
+ fpu_ymm5_i386,
+ fpu_ymm6_i386,
+ fpu_ymm7_i386,
+ k_last_avx_i386 = fpu_ymm7_i386,
+
+ dr0_i386,
+ dr1_i386,
+ dr2_i386,
+ dr3_i386,
+ dr4_i386,
+ dr5_i386,
+ dr6_i386,
+ dr7_i386,
+
+ k_num_registers_i386,
+ k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1,
+ k_num_fpr_registers_i386 = k_last_fpr_i386 - k_first_fpr_i386 + 1,
+ k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1
+};
+
+//---------------------------------------------------------------------------
+// Internal codes for all x86_64 registers.
+//---------------------------------------------------------------------------
+enum
+{
+ k_first_gpr_x86_64,
+ gpr_rax_x86_64 = k_first_gpr_x86_64,
+ gpr_rbx_x86_64,
+ gpr_rcx_x86_64,
+ gpr_rdx_x86_64,
+ gpr_rdi_x86_64,
+ gpr_rsi_x86_64,
+ gpr_rbp_x86_64,
+ gpr_rsp_x86_64,
+ gpr_r8_x86_64,
+ gpr_r9_x86_64,
+ gpr_r10_x86_64,
+ gpr_r11_x86_64,
+ gpr_r12_x86_64,
+ gpr_r13_x86_64,
+ gpr_r14_x86_64,
+ gpr_r15_x86_64,
+ gpr_rip_x86_64,
+ gpr_rflags_x86_64,
+ gpr_cs_x86_64,
+ gpr_fs_x86_64,
+ gpr_gs_x86_64,
+ gpr_ss_x86_64,
+ gpr_ds_x86_64,
+ gpr_es_x86_64,
+
+ k_first_alias_x86_64,
+ gpr_eax_x86_64 = k_first_alias_x86_64,
+ gpr_ebx_x86_64,
+ gpr_ecx_x86_64,
+ gpr_edx_x86_64,
+ gpr_edi_x86_64,
+ gpr_esi_x86_64,
+ gpr_ebp_x86_64,
+ gpr_esp_x86_64,
+ gpr_r8d_x86_64, // Low 32 bits of r8
+ gpr_r9d_x86_64, // Low 32 bits of r9
+ gpr_r10d_x86_64, // Low 32 bits of r10
+ gpr_r11d_x86_64, // Low 32 bits of r11
+ gpr_r12d_x86_64, // Low 32 bits of r12
+ gpr_r13d_x86_64, // Low 32 bits of r13
+ gpr_r14d_x86_64, // Low 32 bits of r14
+ gpr_r15d_x86_64, // Low 32 bits of r15
+ gpr_ax_x86_64,
+ gpr_bx_x86_64,
+ gpr_cx_x86_64,
+ gpr_dx_x86_64,
+ gpr_di_x86_64,
+ gpr_si_x86_64,
+ gpr_bp_x86_64,
+ gpr_sp_x86_64,
+ gpr_r8w_x86_64, // Low 16 bits of r8
+ gpr_r9w_x86_64, // Low 16 bits of r9
+ gpr_r10w_x86_64, // Low 16 bits of r10
+ gpr_r11w_x86_64, // Low 16 bits of r11
+ gpr_r12w_x86_64, // Low 16 bits of r12
+ gpr_r13w_x86_64, // Low 16 bits of r13
+ gpr_r14w_x86_64, // Low 16 bits of r14
+ gpr_r15w_x86_64, // Low 16 bits of r15
+ gpr_ah_x86_64,
+ gpr_bh_x86_64,
+ gpr_ch_x86_64,
+ gpr_dh_x86_64,
+ gpr_al_x86_64,
+ gpr_bl_x86_64,
+ gpr_cl_x86_64,
+ gpr_dl_x86_64,
+ gpr_dil_x86_64,
+ gpr_sil_x86_64,
+ gpr_bpl_x86_64,
+ gpr_spl_x86_64,
+ gpr_r8l_x86_64, // Low 8 bits of r8
+ gpr_r9l_x86_64, // Low 8 bits of r9
+ gpr_r10l_x86_64, // Low 8 bits of r10
+ gpr_r11l_x86_64, // Low 8 bits of r11
+ gpr_r12l_x86_64, // Low 8 bits of r12
+ gpr_r13l_x86_64, // Low 8 bits of r13
+ gpr_r14l_x86_64, // Low 8 bits of r14
+ gpr_r15l_x86_64, // Low 8 bits of r15
+ k_last_alias_x86_64 = gpr_r15l_x86_64,
+
+ k_last_gpr_x86_64 = k_last_alias_x86_64,
+
+ k_first_fpr_x86_64,
+ fpu_fctrl_x86_64 = k_first_fpr_x86_64,
+ fpu_fstat_x86_64,
+ fpu_ftag_x86_64,
+ fpu_fop_x86_64,
+ fpu_fiseg_x86_64,
+ fpu_fioff_x86_64,
+ fpu_foseg_x86_64,
+ fpu_fooff_x86_64,
+ fpu_mxcsr_x86_64,
+ fpu_mxcsrmask_x86_64,
+ fpu_st0_x86_64,
+ fpu_st1_x86_64,
+ fpu_st2_x86_64,
+ fpu_st3_x86_64,
+ fpu_st4_x86_64,
+ fpu_st5_x86_64,
+ fpu_st6_x86_64,
+ fpu_st7_x86_64,
+ fpu_mm0_x86_64,
+ fpu_mm1_x86_64,
+ fpu_mm2_x86_64,
+ fpu_mm3_x86_64,
+ fpu_mm4_x86_64,
+ fpu_mm5_x86_64,
+ fpu_mm6_x86_64,
+ fpu_mm7_x86_64,
+ fpu_xmm0_x86_64,
+ fpu_xmm1_x86_64,
+ fpu_xmm2_x86_64,
+ fpu_xmm3_x86_64,
+ fpu_xmm4_x86_64,
+ fpu_xmm5_x86_64,
+ fpu_xmm6_x86_64,
+ fpu_xmm7_x86_64,
+ fpu_xmm8_x86_64,
+ fpu_xmm9_x86_64,
+ fpu_xmm10_x86_64,
+ fpu_xmm11_x86_64,
+ fpu_xmm12_x86_64,
+ fpu_xmm13_x86_64,
+ fpu_xmm14_x86_64,
+ fpu_xmm15_x86_64,
+ k_last_fpr_x86_64 = fpu_xmm15_x86_64,
+
+ k_first_avx_x86_64,
+ fpu_ymm0_x86_64 = k_first_avx_x86_64,
+ fpu_ymm1_x86_64,
+ fpu_ymm2_x86_64,
+ fpu_ymm3_x86_64,
+ fpu_ymm4_x86_64,
+ fpu_ymm5_x86_64,
+ fpu_ymm6_x86_64,
+ fpu_ymm7_x86_64,
+ fpu_ymm8_x86_64,
+ fpu_ymm9_x86_64,
+ fpu_ymm10_x86_64,
+ fpu_ymm11_x86_64,
+ fpu_ymm12_x86_64,
+ fpu_ymm13_x86_64,
+ fpu_ymm14_x86_64,
+ fpu_ymm15_x86_64,
+ k_last_avx_x86_64 = fpu_ymm15_x86_64,
+
+ dr0_x86_64,
+ dr1_x86_64,
+ dr2_x86_64,
+ dr3_x86_64,
+ dr4_x86_64,
+ dr5_x86_64,
+ dr6_x86_64,
+ dr7_x86_64,
+
+ k_num_registers_x86_64,
+ k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1,
+ k_num_fpr_registers_x86_64 = k_last_fpr_x86_64 - k_first_fpr_x86_64 + 1,
+ k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1
+};
+
+class RegisterContextPOSIX_x86
+ : public lldb_private::RegisterContext
+{
+public:
+ RegisterContextPOSIX_x86 (lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info);
+
+ ~RegisterContextPOSIX_x86();
+
+ 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(uint32_t kind, uint32_t num);
+
+ //---------------------------------------------------------------------------
+ // Note: prefer kernel definitions over user-land
+ //---------------------------------------------------------------------------
+ enum FPRType
+ {
+ eNotValid = 0,
+ eFSAVE, // TODO
+ eFXSAVE,
+ eSOFT, // TODO
+ eXSAVE
+ };
+
+ static uint32_t g_contained_eax[];
+ static uint32_t g_contained_ebx[];
+ static uint32_t g_contained_ecx[];
+ static uint32_t g_contained_edx[];
+ static uint32_t g_contained_edi[];
+ static uint32_t g_contained_esi[];
+ static uint32_t g_contained_ebp[];
+ static uint32_t g_contained_esp[];
+
+ static uint32_t g_invalidate_eax[];
+ static uint32_t g_invalidate_ebx[];
+ static uint32_t g_invalidate_ecx[];
+ static uint32_t g_invalidate_edx[];
+ static uint32_t g_invalidate_edi[];
+ static uint32_t g_invalidate_esi[];
+ static uint32_t g_invalidate_ebp[];
+ static uint32_t g_invalidate_esp[];
+
+ static uint32_t g_contained_rax[];
+ static uint32_t g_contained_rbx[];
+ static uint32_t g_contained_rcx[];
+ static uint32_t g_contained_rdx[];
+ static uint32_t g_contained_rdi[];
+ static uint32_t g_contained_rsi[];
+ static uint32_t g_contained_rbp[];
+ static uint32_t g_contained_rsp[];
+ static uint32_t g_contained_r8[];
+ static uint32_t g_contained_r9[];
+ static uint32_t g_contained_r10[];
+ static uint32_t g_contained_r11[];
+ static uint32_t g_contained_r12[];
+ static uint32_t g_contained_r13[];
+ static uint32_t g_contained_r14[];
+ static uint32_t g_contained_r15[];
+
+ static uint32_t g_invalidate_rax[];
+ static uint32_t g_invalidate_rbx[];
+ static uint32_t g_invalidate_rcx[];
+ static uint32_t g_invalidate_rdx[];
+ static uint32_t g_invalidate_rdi[];
+ static uint32_t g_invalidate_rsi[];
+ static uint32_t g_invalidate_rbp[];
+ static uint32_t g_invalidate_rsp[];
+ static uint32_t g_invalidate_r8[];
+ static uint32_t g_invalidate_r9[];
+ static uint32_t g_invalidate_r10[];
+ static uint32_t g_invalidate_r11[];
+ static uint32_t g_invalidate_r12[];
+ static uint32_t g_invalidate_r13[];
+ static uint32_t g_invalidate_r14[];
+ static uint32_t g_invalidate_r15[];
+
+protected:
+ struct RegInfo
+ {
+ uint32_t num_registers;
+ uint32_t num_gpr_registers;
+ uint32_t num_fpr_registers;
+ uint32_t num_avx_registers;
+
+ uint32_t last_gpr;
+ uint32_t first_fpr;
+ uint32_t last_fpr;
+
+ uint32_t first_st;
+ uint32_t last_st;
+ uint32_t first_mm;
+ uint32_t last_mm;
+ uint32_t first_xmm;
+ uint32_t last_xmm;
+ uint32_t first_ymm;
+ uint32_t last_ymm;
+
+ uint32_t first_dr;
+ uint32_t gpr_flags;
+ };
+
+ uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64]; // 64-bit general purpose registers.
+ RegInfo m_reg_info;
+ FPRType m_fpr_type; // determines the type of data stored by union FPR, if any.
+ FPR m_fpr; // floating-point registers including extended register sets.
+ 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)
+
+ // 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);
+
+ bool
+ IsAVX(unsigned reg);
+
+ lldb::ByteOrder GetByteOrder();
+
+ bool CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order);
+ bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);
+ bool IsFPR(unsigned reg, FPRType fpr_type);
+ FPRType GetFPRType();
+
+ virtual bool ReadGPR() = 0;
+ virtual bool ReadFPR() = 0;
+ virtual bool WriteGPR() = 0;
+ virtual bool WriteFPR() = 0;
+};
+
+#endif // #ifndef liblldb_RegisterContextPOSIX_x86_H_
diff --git a/source/Plugins/Process/POSIX/RegisterContext_i386.cpp b/source/Plugins/Process/POSIX/RegisterContext_i386.cpp
deleted file mode 100644
index 49676bd3fc73..000000000000
--- a/source/Plugins/Process/POSIX/RegisterContext_i386.cpp
+++ /dev/null
@@ -1,551 +0,0 @@
-//===-- RegisterContextPOSIX_i386.cpp ---------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Host/Endian.h"
-#include "llvm/Support/Compiler.h"
-
-#include "ProcessPOSIX.h"
-#include "ProcessPOSIXLog.h"
-#include "ProcessMonitor.h"
-#include "RegisterContext_i386.h"
-#include "RegisterContext_x86.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-enum
-{
- k_first_gpr,
- gpr_eax = k_first_gpr,
- gpr_ebx,
- gpr_ecx,
- gpr_edx,
- gpr_edi,
- gpr_esi,
- gpr_ebp,
- gpr_esp,
- gpr_ss,
- gpr_eflags,
-#ifdef __FreeBSD__
- gpr_orig_ax,
-#endif
- gpr_eip,
- gpr_cs,
- gpr_ds,
- gpr_es,
- gpr_fs,
- gpr_gs,
- k_last_gpr = gpr_gs,
-
- k_first_fpr,
- fpu_fcw = k_first_fpr,
- fpu_fsw,
- fpu_ftw,
- fpu_fop,
- fpu_ip,
- fpu_cs,
- fpu_foo,
- fpu_fos,
- fpu_mxcsr,
- fpu_stmm0,
- fpu_stmm1,
- fpu_stmm2,
- fpu_stmm3,
- fpu_stmm4,
- fpu_stmm5,
- fpu_stmm6,
- fpu_stmm7,
- fpu_xmm0,
- fpu_xmm1,
- fpu_xmm2,
- fpu_xmm3,
- fpu_xmm4,
- fpu_xmm5,
- fpu_xmm6,
- fpu_xmm7,
- k_last_fpr = fpu_xmm7,
-
- k_num_registers,
- k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
- k_num_fpu_registers = k_last_fpr - k_first_fpr + 1
-};
-
-// Number of register sets provided by this context.
-enum
-{
- k_num_register_sets = 2
-};
-
-static const
-uint32_t g_gpr_regnums[k_num_gpr_registers] =
-{
- gpr_eax,
- gpr_ebx,
- gpr_ecx,
- gpr_edx,
- gpr_edi,
- gpr_esi,
- gpr_ebp,
- gpr_esp,
- gpr_ss,
- gpr_eflags,
-#ifdef __FreeBSD__
- gpr_orig_ax,
-#endif
- gpr_eip,
- gpr_cs,
- gpr_ds,
- gpr_es,
- gpr_fs,
- gpr_gs,
-};
-
-static const uint32_t
-g_fpu_regnums[k_num_fpu_registers] =
-{
- fpu_fcw,
- fpu_fsw,
- fpu_ftw,
- fpu_fop,
- fpu_ip,
- fpu_cs,
- fpu_foo,
- fpu_fos,
- fpu_mxcsr,
- fpu_stmm0,
- fpu_stmm1,
- fpu_stmm2,
- fpu_stmm3,
- fpu_stmm4,
- fpu_stmm5,
- fpu_stmm6,
- fpu_stmm7,
- fpu_xmm0,
- fpu_xmm1,
- fpu_xmm2,
- fpu_xmm3,
- fpu_xmm4,
- fpu_xmm5,
- fpu_xmm6,
- fpu_xmm7,
-};
-
-static const RegisterSet
-g_reg_sets[k_num_register_sets] =
-{
- { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
- { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums }
-};
-
-// Computes the offset of the given GPR in the user data area.
-#define GPR_OFFSET(regname) \
- (offsetof(RegisterContext_i386::UserArea, regs) + \
- offsetof(RegisterContext_i386::GPR, regname))
-
-// Computes the offset of the given FPR in the user data area.
-#define FPR_OFFSET(regname) \
- (offsetof(RegisterContext_i386::UserArea, i387) + \
- offsetof(RegisterContext_i386::FPU, regname))
-
-// Number of bytes needed to represent a GPR.
-#define GPR_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg)
-
-// Number of bytes needed to represent a FPR.
-#define FPR_SIZE(reg) sizeof(((RegisterContext_i386::FPU*)NULL)->reg)
-
-// Number of bytes needed to represent the i'th FP register.
-#define FP_SIZE sizeof(((RegisterContext_i386::MMSReg*)NULL)->bytes)
-
-// Number of bytes needed to represent an XMM register.
-#define XMM_SIZE sizeof(RegisterContext_i386::XMMReg)
-
-#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
- { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg }, NULL, NULL }
-
-#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \
- { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg }, NULL, NULL }
-
-#define DEFINE_FP(reg, i) \
- { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
- eEncodingVector, eFormatVectorOfUInt8, \
- { dwarf_##reg##i, dwarf_##reg##i, \
- LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL }
-
-#define DEFINE_XMM(reg, i) \
- { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
- eEncodingVector, eFormatVectorOfUInt8, \
- { dwarf_##reg##i, dwarf_##reg##i, \
- LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL }
-
-static RegisterInfo
-g_register_infos[k_num_registers] =
-{
- // General purpose registers.
- DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax),
- DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx),
- DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx),
- DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx),
- DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi),
- DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi),
- DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp),
- DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp),
- DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss),
- DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags),
- DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip),
- DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs),
- DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds),
- DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es),
- DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs),
- DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs),
-
- // Floating point registers.
- DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw),
- DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw),
- DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw),
- DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop),
- DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip),
- DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs),
- DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp),
- DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds),
- DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr),
-
- DEFINE_FP(stmm, 0),
- DEFINE_FP(stmm, 1),
- DEFINE_FP(stmm, 2),
- DEFINE_FP(stmm, 3),
- DEFINE_FP(stmm, 4),
- DEFINE_FP(stmm, 5),
- DEFINE_FP(stmm, 6),
- DEFINE_FP(stmm, 7),
-
- // XMM registers
- DEFINE_XMM(xmm, 0),
- DEFINE_XMM(xmm, 1),
- DEFINE_XMM(xmm, 2),
- DEFINE_XMM(xmm, 3),
- DEFINE_XMM(xmm, 4),
- DEFINE_XMM(xmm, 5),
- DEFINE_XMM(xmm, 6),
- DEFINE_XMM(xmm, 7),
-
-};
-
-#ifndef NDEBUG
-static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
-#endif
-
-static unsigned GetRegOffset(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register number.");
- return g_register_infos[reg].byte_offset;
-}
-
-static unsigned GetRegSize(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register number.");
- return g_register_infos[reg].byte_size;
-}
-
-RegisterContext_i386::RegisterContext_i386(Thread &thread,
- uint32_t concrete_frame_idx)
- : RegisterContextPOSIX(thread, concrete_frame_idx)
-{
-}
-
-RegisterContext_i386::~RegisterContext_i386()
-{
-}
-
-ProcessMonitor &
-RegisterContext_i386::GetMonitor()
-{
- ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
- return process->GetMonitor();
-}
-
-void
-RegisterContext_i386::Invalidate()
-{
-}
-
-void
-RegisterContext_i386::InvalidateAllRegisters()
-{
-}
-
-size_t
-RegisterContext_i386::GetRegisterCount()
-{
- assert(k_num_register_infos == k_num_registers);
- return k_num_registers;
-}
-
-const RegisterInfo *
-RegisterContext_i386::GetRegisterInfoAtIndex(size_t reg)
-{
- assert(k_num_register_infos == k_num_registers);
- if (reg < k_num_registers)
- return &g_register_infos[reg];
- else
- return NULL;
-}
-
-size_t
-RegisterContext_i386::GetRegisterSetCount()
-{
- return k_num_register_sets;
-}
-
-const RegisterSet *
-RegisterContext_i386::GetRegisterSet(size_t set)
-{
- if (set < k_num_register_sets)
- return &g_reg_sets[set];
- else
- return NULL;
-}
-
-unsigned
-RegisterContext_i386::GetRegisterIndexFromOffset(unsigned offset)
-{
- unsigned reg;
- for (reg = 0; reg < k_num_registers; reg++)
- {
- if (g_register_infos[reg].byte_offset == offset)
- break;
- }
- assert(reg < k_num_registers && "Invalid register offset.");
- return reg;
-}
-
-const char *
-RegisterContext_i386::GetRegisterName(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register offset.");
- return g_register_infos[reg].name;
-}
-
-bool
-RegisterContext_i386::ReadRegister(const RegisterInfo *reg_info,
- RegisterValue &value)
-{
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(m_thread.GetID(), GetRegOffset(reg),
- GetRegisterName(reg), GetRegSize(reg), value);
-}
-
-bool
-RegisterContext_i386::ReadAllRegisterValues(DataBufferSP &data_sp)
-{
- return false;
-}
-
-bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info,
- const RegisterValue &value)
-{
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(m_thread.GetID(), GetRegOffset(reg),
- GetRegisterName(reg), value);
-}
-
-bool
-RegisterContext_i386::WriteAllRegisterValues(const DataBufferSP &data)
-{
- return false;
-}
-
-bool
-RegisterContext_i386::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;
-}
-
-uint32_t
-RegisterContext_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind,
- uint32_t num)
-{
- if (kind == eRegisterKindGeneric)
- {
- switch (num)
- {
- case LLDB_REGNUM_GENERIC_PC: return gpr_eip;
- case LLDB_REGNUM_GENERIC_SP: return gpr_esp;
- case LLDB_REGNUM_GENERIC_FP: return gpr_ebp;
- case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags;
- case LLDB_REGNUM_GENERIC_RA:
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
- {
- switch (num)
- {
- case dwarf_eax: return gpr_eax;
- case dwarf_edx: return gpr_edx;
- case dwarf_ecx: return gpr_ecx;
- case dwarf_ebx: return gpr_ebx;
- case dwarf_esi: return gpr_esi;
- case dwarf_edi: return gpr_edi;
- case dwarf_ebp: return gpr_ebp;
- case dwarf_esp: return gpr_esp;
- case dwarf_eip: return gpr_eip;
- case dwarf_xmm0: return fpu_xmm0;
- case dwarf_xmm1: return fpu_xmm1;
- case dwarf_xmm2: return fpu_xmm2;
- case dwarf_xmm3: return fpu_xmm3;
- case dwarf_xmm4: return fpu_xmm4;
- case dwarf_xmm5: return fpu_xmm5;
- case dwarf_xmm6: return fpu_xmm6;
- case dwarf_xmm7: return fpu_xmm7;
- case dwarf_stmm0: return fpu_stmm0;
- case dwarf_stmm1: return fpu_stmm1;
- case dwarf_stmm2: return fpu_stmm2;
- case dwarf_stmm3: return fpu_stmm3;
- case dwarf_stmm4: return fpu_stmm4;
- case dwarf_stmm5: return fpu_stmm5;
- case dwarf_stmm6: return fpu_stmm6;
- case dwarf_stmm7: return fpu_stmm7;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGDB)
- {
- switch (num)
- {
- case gdb_eax : return gpr_eax;
- case gdb_ebx : return gpr_ebx;
- case gdb_ecx : return gpr_ecx;
- case gdb_edx : return gpr_edx;
- case gdb_esi : return gpr_esi;
- case gdb_edi : return gpr_edi;
- case gdb_ebp : return gpr_ebp;
- case gdb_esp : return gpr_esp;
- case gdb_eip : return gpr_eip;
- case gdb_eflags : return gpr_eflags;
- case gdb_cs : return gpr_cs;
- case gdb_ss : return gpr_ss;
- case gdb_ds : return gpr_ds;
- case gdb_es : return gpr_es;
- case gdb_fs : return gpr_fs;
- case gdb_gs : return gpr_gs;
- case gdb_stmm0 : return fpu_stmm0;
- case gdb_stmm1 : return fpu_stmm1;
- case gdb_stmm2 : return fpu_stmm2;
- case gdb_stmm3 : return fpu_stmm3;
- case gdb_stmm4 : return fpu_stmm4;
- case gdb_stmm5 : return fpu_stmm5;
- case gdb_stmm6 : return fpu_stmm6;
- case gdb_stmm7 : return fpu_stmm7;
- case gdb_fcw : return fpu_fcw;
- case gdb_fsw : return fpu_fsw;
- case gdb_ftw : return fpu_ftw;
- case gdb_fpu_cs : return fpu_cs;
- case gdb_ip : return fpu_ip;
- case gdb_fpu_ds : return fpu_fos;
- case gdb_dp : return fpu_foo;
- case gdb_fop : return fpu_fop;
- case gdb_xmm0 : return fpu_xmm0;
- case gdb_xmm1 : return fpu_xmm1;
- case gdb_xmm2 : return fpu_xmm2;
- case gdb_xmm3 : return fpu_xmm3;
- case gdb_xmm4 : return fpu_xmm4;
- case gdb_xmm5 : return fpu_xmm5;
- case gdb_xmm6 : return fpu_xmm6;
- case gdb_xmm7 : return fpu_xmm7;
- case gdb_mxcsr : return fpu_mxcsr;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
- else if (kind == eRegisterKindLLDB)
- {
- return num;
- }
-
- return LLDB_INVALID_REGNUM;
-}
-
-bool
-RegisterContext_i386::HardwareSingleStep(bool enable)
-{
- enum { TRACE_BIT = 0x100 };
- uint64_t eflags;
-
- if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL)
- return false;
-
- if (enable)
- {
- if (eflags & TRACE_BIT)
- return true;
-
- eflags |= TRACE_BIT;
- }
- else
- {
- if (!(eflags & TRACE_BIT))
- return false;
-
- eflags &= ~TRACE_BIT;
- }
-
- return WriteRegisterFromUnsigned(gpr_eflags, eflags);
-}
-
-void
-RegisterContext_i386::LogGPR(const char *title)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
- if (log)
- {
- if (title)
- log->Printf ("%s", title);
- for (uint32_t i=0; i<k_num_gpr_registers; i++)
- {
- uint32_t reg = gpr_eax + i;
- log->Printf("%12s = 0x%8.8" PRIx64, g_register_infos[reg].name, ((uint64_t*)&user.regs)[reg]);
- }
- }
-}
-
-bool
-RegisterContext_i386::ReadGPR()
-{
- bool result;
-
- ProcessMonitor &monitor = GetMonitor();
- result = monitor.ReadGPR(m_thread.GetID(), &user.regs, sizeof(user.regs));
- LogGPR("RegisterContext_i386::ReadGPR()");
- return result;
-}
-
-bool
-RegisterContext_i386::ReadFPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadFPR(m_thread.GetID(), &user.i387, sizeof(user.i387));
-}
diff --git a/source/Plugins/Process/POSIX/RegisterContext_i386.h b/source/Plugins/Process/POSIX/RegisterContext_i386.h
deleted file mode 100644
index 96066c47b815..000000000000
--- a/source/Plugins/Process/POSIX/RegisterContext_i386.h
+++ /dev/null
@@ -1,169 +0,0 @@
-//===-- RegisterContext_i386.h ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContext_i386_h_
-#define liblldb_RegisterContext_i386_h_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/Log.h"
-#include "RegisterContextPOSIX.h"
-
-class RegisterContext_i386 : public RegisterContextPOSIX
-{
-public:
- RegisterContext_i386(lldb_private::Thread &thread,
- uint32_t concreate_frame_idx);
-
- ~RegisterContext_i386();
-
- void
- Invalidate();
-
- void
- InvalidateAllRegisters();
-
- size_t
- GetRegisterCount();
-
- const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
-
- size_t
- GetRegisterSetCount();
-
- const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
-
- unsigned
- GetRegisterIndexFromOffset(unsigned offset);
-
- const char *
- GetRegisterName(unsigned reg);
-
- bool
- ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value);
-
- bool
- ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data);
-
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value);
-
- bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
-
- bool
- WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value);
-
- bool
- WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data,
- uint32_t data_offset = 0);
-
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value);
-
- bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
-
- uint32_t
- ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
-
- bool
- HardwareSingleStep(bool enable);
-
- bool
- UpdateAfterBreakpoint();
-
- struct GPR
- {
- uint32_t ebx;
- uint32_t ecx;
- uint32_t edx;
- uint32_t esi;
- uint32_t edi;
- uint32_t ebp;
- uint32_t eax;
- uint32_t ds;
- uint32_t es;
- uint32_t fs;
- uint32_t gs;
- uint32_t orig_ax;
- uint32_t eip;
- uint32_t cs;
- uint32_t eflags;
- uint32_t esp;
- uint32_t ss;
- };
-
- struct MMSReg
- {
- uint8_t bytes[8];
- };
-
- struct XMMReg
- {
- uint8_t bytes[16];
- };
-
- struct FPU
- {
- uint16_t fcw;
- uint16_t fsw;
- uint16_t ftw;
- uint16_t fop;
- uint32_t ip;
- uint32_t cs;
- uint32_t foo;
- uint32_t fos;
- uint32_t mxcsr;
- uint32_t reserved;
- MMSReg stmm[8];
- XMMReg xmm[8];
- uint32_t pad[56];
- };
-
- // A user area like this no longer exists on FreeBSD
- // making this a Linux artifact. Nonetheless, it is safe
- // leaving it here while the code is being cleaned up and generalized.
-
- struct UserArea
- {
- GPR regs; // General purpose registers.
- int32_t fpvalid; // True if FPU is being used.
- FPU i387; // FPU registers.
- uint32_t tsize; // Text segment size.
- uint32_t dsize; // Data segment size.
- uint32_t ssize; // Stack segment size.
- uint32_t start_code; // VM address of text.
- uint32_t start_stack; // VM address of stack bottom (top in rsp).
- int32_t signal; // Signal causing core dump.
- int32_t reserved; // Unused.
- uint32_t ar0; // Location of GPR's.
- FPU* fpstate; // Location of FPR's.
- uint32_t magic; // Identifier for core dumps.
- char u_comm[32]; // Command causing core dump.
- uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7).
- };
-private:
- UserArea user;
-
- ProcessMonitor &GetMonitor();
-
- void LogGPR(const char *title);
-
- bool ReadGPR();
- bool ReadFPR();
-};
-
-#endif // #ifndef liblldb_RegisterContext_i386_h_
diff --git a/source/Plugins/Process/POSIX/RegisterContext_mips64.h b/source/Plugins/Process/POSIX/RegisterContext_mips64.h
new file mode 100644
index 000000000000..dfd473d7cbec
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContext_mips64.h
@@ -0,0 +1,104 @@
+//===-- RegisterContext_mips64.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContext_mips64_H_
+#define liblldb_RegisterContext_mips64_H_
+
+// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF)
+enum
+{
+ // GP Registers
+ gcc_dwarf_zero_mips64 = 0,
+ gcc_dwarf_r1_mips64,
+ gcc_dwarf_r2_mips64,
+ gcc_dwarf_r3_mips64,
+ gcc_dwarf_r4_mips64,
+ gcc_dwarf_r5_mips64,
+ gcc_dwarf_r6_mips64,
+ gcc_dwarf_r7_mips64,
+ gcc_dwarf_r8_mips64,
+ gcc_dwarf_r9_mips64,
+ gcc_dwarf_r10_mips64,
+ gcc_dwarf_r11_mips64,
+ gcc_dwarf_r12_mips64,
+ gcc_dwarf_r13_mips64,
+ gcc_dwarf_r14_mips64,
+ gcc_dwarf_r15_mips64,
+ gcc_dwarf_r16_mips64,
+ gcc_dwarf_r17_mips64,
+ gcc_dwarf_r18_mips64,
+ gcc_dwarf_r19_mips64,
+ gcc_dwarf_r20_mips64,
+ gcc_dwarf_r21_mips64,
+ gcc_dwarf_r22_mips64,
+ gcc_dwarf_r23_mips64,
+ gcc_dwarf_r24_mips64,
+ gcc_dwarf_r25_mips64,
+ gcc_dwarf_r26_mips64,
+ gcc_dwarf_r27_mips64,
+ gcc_dwarf_gp_mips64,
+ gcc_dwarf_sp_mips64,
+ gcc_dwarf_r30_mips64,
+ gcc_dwarf_ra_mips64,
+ gcc_dwarf_sr_mips64,
+ gcc_dwarf_lo_mips64,
+ gcc_dwarf_hi_mips64,
+ gcc_dwarf_bad_mips64,
+ gcc_dwarf_cause_mips64,
+ gcc_dwarf_pc_mips64,
+ gcc_dwarf_ic_mips64,
+ gcc_dwarf_dummy_mips64
+};
+
+// GDB Register numbers (eRegisterKindGDB)
+enum
+{
+ gdb_zero_mips64 = 0,
+ gdb_r1_mips64,
+ gdb_r2_mips64,
+ gdb_r3_mips64,
+ gdb_r4_mips64,
+ gdb_r5_mips64,
+ gdb_r6_mips64,
+ gdb_r7_mips64,
+ gdb_r8_mips64,
+ gdb_r9_mips64,
+ gdb_r10_mips64,
+ gdb_r11_mips64,
+ gdb_r12_mips64,
+ gdb_r13_mips64,
+ gdb_r14_mips64,
+ gdb_r15_mips64,
+ gdb_r16_mips64,
+ gdb_r17_mips64,
+ gdb_r18_mips64,
+ gdb_r19_mips64,
+ gdb_r20_mips64,
+ gdb_r21_mips64,
+ gdb_r22_mips64,
+ gdb_r23_mips64,
+ gdb_r24_mips64,
+ gdb_r25_mips64,
+ gdb_r26_mips64,
+ gdb_r27_mips64,
+ gdb_gp_mips64,
+ gdb_sp_mips64,
+ gdb_r30_mips64,
+ gdb_ra_mips64,
+ gdb_sr_mips64,
+ gdb_lo_mips64,
+ gdb_hi_mips64,
+ gdb_bad_mips64,
+ gdb_cause_mips64,
+ gdb_pc_mips64,
+ gdb_ic_mips64,
+ gdb_dummy_mips64
+};
+
+#endif // liblldb_RegisterContext_mips64_H_
diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86.h b/source/Plugins/Process/POSIX/RegisterContext_x86.h
index 61a25c407758..df3e1e5a84bf 100644
--- a/source/Plugins/Process/POSIX/RegisterContext_x86.h
+++ b/source/Plugins/Process/POSIX/RegisterContext_x86.h
@@ -1,4 +1,4 @@
-//===-- RegisterContext_x86.h ---------------------------*- C++ -*-===//
+//===-- RegisterContext_x86.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,101 +10,470 @@
#ifndef liblldb_RegisterContext_x86_H_
#define liblldb_RegisterContext_x86_H_
+//---------------------------------------------------------------------------
+// i386 gcc, dwarf, gdb enums
+//---------------------------------------------------------------------------
+
+// Register numbers seen in eh_frame (eRegisterKindGCC)
+//
+// From Jason Molenda: "gcc registers" is the register numbering used in the eh_frame
+// CFI. The only registers that are described in eh_frame CFI are those that are
+// preserved across function calls aka callee-saved aka non-volatile. And none
+// of the floating point registers on x86 are preserved across function calls.
+//
+// The only reason there is a "gcc register" and a "dwarf register" is because of a
+// mistake years and years ago with i386 where they got esp and ebp
+// backwards when they emitted the eh_frame instructions. Once there were
+// binaries In The Wild using the reversed numbering, we had to stick with it
+// forever.
+enum
+{
+ // 2nd parameter in DwarfRegNum() is regnum for exception handling on x86-32.
+ // See http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register
+ gcc_eax_i386 = 0,
+ gcc_ecx_i386,
+ gcc_edx_i386,
+ gcc_ebx_i386,
+ gcc_ebp_i386, // Warning: these are switched from dwarf values
+ gcc_esp_i386, //
+ gcc_esi_i386,
+ gcc_edi_i386,
+ gcc_eip_i386,
+ gcc_eflags_i386,
+ gcc_st0_i386 = 12,
+ gcc_st1_i386,
+ gcc_st2_i386,
+ gcc_st3_i386,
+ gcc_st4_i386,
+ gcc_st5_i386,
+ gcc_st6_i386,
+ gcc_st7_i386,
+ gcc_xmm0_i386 = 21,
+ gcc_xmm1_i386,
+ gcc_xmm2_i386,
+ gcc_xmm3_i386,
+ gcc_xmm4_i386,
+ gcc_xmm5_i386,
+ gcc_xmm6_i386,
+ gcc_xmm7_i386,
+ gcc_mm0_i386 = 29,
+ gcc_mm1_i386,
+ gcc_mm2_i386,
+ gcc_mm3_i386,
+ gcc_mm4_i386,
+ gcc_mm5_i386,
+ gcc_mm6_i386,
+ gcc_mm7_i386,
+};
+
+// DWARF register numbers (eRegisterKindDWARF)
+// Intel's x86 or IA-32
enum
{
- gcc_eax = 0,
- gcc_ecx,
- gcc_edx,
- gcc_ebx,
- gcc_ebp,
- gcc_esp,
- gcc_esi,
- gcc_edi,
- gcc_eip,
- gcc_eflags
+ // General Purpose Registers.
+ dwarf_eax_i386 = 0,
+ dwarf_ecx_i386,
+ dwarf_edx_i386,
+ dwarf_ebx_i386,
+ dwarf_esp_i386,
+ dwarf_ebp_i386,
+ dwarf_esi_i386,
+ dwarf_edi_i386,
+ dwarf_eip_i386,
+ dwarf_eflags_i386,
+ // Floating Point Registers
+ dwarf_st0_i386 = 11,
+ dwarf_st1_i386,
+ dwarf_st2_i386,
+ dwarf_st3_i386,
+ dwarf_st4_i386,
+ dwarf_st5_i386,
+ dwarf_st6_i386,
+ dwarf_st7_i386,
+ // SSE Registers
+ dwarf_xmm0_i386 = 21,
+ dwarf_xmm1_i386,
+ dwarf_xmm2_i386,
+ dwarf_xmm3_i386,
+ dwarf_xmm4_i386,
+ dwarf_xmm5_i386,
+ dwarf_xmm6_i386,
+ dwarf_xmm7_i386,
+ // MMX Registers
+ dwarf_mm0_i386 = 29,
+ dwarf_mm1_i386,
+ dwarf_mm2_i386,
+ dwarf_mm3_i386,
+ dwarf_mm4_i386,
+ dwarf_mm5_i386,
+ dwarf_mm6_i386,
+ dwarf_mm7_i386,
+ dwarf_fctrl_i386 = 37, // x87 control word
+ dwarf_fstat_i386 = 38, // x87 status word
+ dwarf_mxcsr_i386 = 39,
+ dwarf_es_i386 = 40,
+ dwarf_cs_i386 = 41,
+ dwarf_ss_i386 = 42,
+ dwarf_ds_i386 = 43,
+ dwarf_fs_i386 = 44,
+ dwarf_gs_i386 = 45
+
+ // I believe the ymm registers use the dwarf_xmm%_i386 register numbers and
+ // then differentiate based on size of the register.
};
+// Register numbers GDB uses (eRegisterKindGDB)
+//
+// From Jason Molenda: The "gdb numbers" are what you would see in the stabs debug format.
enum
{
- dwarf_eax = 0,
- dwarf_ecx,
- dwarf_edx,
- dwarf_ebx,
- dwarf_esp,
- dwarf_ebp,
- dwarf_esi,
- dwarf_edi,
- dwarf_eip,
- dwarf_eflags,
- dwarf_stmm0 = 11,
- dwarf_stmm1,
- dwarf_stmm2,
- dwarf_stmm3,
- dwarf_stmm4,
- dwarf_stmm5,
- dwarf_stmm6,
- dwarf_stmm7,
- dwarf_xmm0 = 21,
- dwarf_xmm1,
- dwarf_xmm2,
- dwarf_xmm3,
- dwarf_xmm4,
- dwarf_xmm5,
- dwarf_xmm6,
- dwarf_xmm7
+ gdb_eax_i386,
+ gdb_ecx_i386,
+ gdb_edx_i386,
+ gdb_ebx_i386,
+ gdb_esp_i386,
+ gdb_ebp_i386,
+ gdb_esi_i386,
+ gdb_edi_i386,
+ gdb_eip_i386,
+ gdb_eflags_i386,
+ gdb_cs_i386,
+ gdb_ss_i386,
+ gdb_ds_i386,
+ gdb_es_i386,
+ gdb_fs_i386,
+ gdb_gs_i386,
+ gdb_st0_i386 = 16,
+ gdb_st1_i386,
+ gdb_st2_i386,
+ gdb_st3_i386,
+ gdb_st4_i386,
+ gdb_st5_i386,
+ gdb_st6_i386,
+ gdb_st7_i386,
+ gdb_fctrl_i386, // FPU Control Word
+ gdb_fstat_i386, // FPU Status Word
+ gdb_ftag_i386, // FPU Tag Word
+ gdb_fiseg_i386, // FPU IP Selector
+ gdb_fioff_i386, // FPU IP Offset
+ gdb_foseg_i386, // FPU Operand Pointer Selector
+ gdb_fooff_i386, // FPU Operand Pointer Offset
+ gdb_fop_i386, // Last Instruction Opcode
+ gdb_xmm0_i386 = 32,
+ gdb_xmm1_i386,
+ gdb_xmm2_i386,
+ gdb_xmm3_i386,
+ gdb_xmm4_i386,
+ gdb_xmm5_i386,
+ gdb_xmm6_i386,
+ gdb_xmm7_i386,
+ gdb_mxcsr_i386 = 40,
+ gdb_ymm0h_i386,
+ gdb_ymm1h_i386,
+ gdb_ymm2h_i386,
+ gdb_ymm3h_i386,
+ gdb_ymm4h_i386,
+ gdb_ymm5h_i386,
+ gdb_ymm6h_i386,
+ gdb_ymm7h_i386,
+ gdb_mm0_i386,
+ gdb_mm1_i386,
+ gdb_mm2_i386,
+ gdb_mm3_i386,
+ gdb_mm4_i386,
+ gdb_mm5_i386,
+ gdb_mm6_i386,
+ gdb_mm7_i386,
};
+//---------------------------------------------------------------------------
+// AMD x86_64, AMD64, Intel EM64T, or Intel 64 gcc, dwarf, gdb enums
+//---------------------------------------------------------------------------
+
+// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF)
+// This is the spec I used (as opposed to x86-64-abi-0.99.pdf):
+// http://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf
enum
{
- gdb_eax = 0,
- gdb_ecx = 1,
- gdb_edx = 2,
- gdb_ebx = 3,
- gdb_esp = 4,
- gdb_ebp = 5,
- gdb_esi = 6,
- gdb_edi = 7,
- gdb_eip = 8,
- gdb_eflags = 9,
- gdb_cs = 10,
- gdb_ss = 11,
- gdb_ds = 12,
- gdb_es = 13,
- gdb_fs = 14,
- gdb_gs = 15,
- gdb_stmm0 = 16,
- gdb_stmm1 = 17,
- gdb_stmm2 = 18,
- gdb_stmm3 = 19,
- gdb_stmm4 = 20,
- gdb_stmm5 = 21,
- gdb_stmm6 = 22,
- gdb_stmm7 = 23,
- gdb_fcw = 24,
- gdb_fsw = 25,
- gdb_ftw = 26,
- gdb_fpu_cs = 27,
- gdb_ip = 28,
- gdb_fpu_ds = 29,
- gdb_dp = 30,
- gdb_fop = 31,
- gdb_xmm0 = 32,
- gdb_xmm1 = 33,
- gdb_xmm2 = 34,
- gdb_xmm3 = 35,
- gdb_xmm4 = 36,
- gdb_xmm5 = 37,
- gdb_xmm6 = 38,
- gdb_xmm7 = 39,
- gdb_mxcsr = 40,
- gdb_mm0 = 41,
- gdb_mm1 = 42,
- gdb_mm2 = 43,
- gdb_mm3 = 44,
- gdb_mm4 = 45,
- gdb_mm5 = 46,
- gdb_mm6 = 47,
- gdb_mm7 = 48
+ // GP Registers
+ gcc_dwarf_rax_x86_64 = 0,
+ gcc_dwarf_rdx_x86_64,
+ gcc_dwarf_rcx_x86_64,
+ gcc_dwarf_rbx_x86_64,
+ gcc_dwarf_rsi_x86_64,
+ gcc_dwarf_rdi_x86_64,
+ gcc_dwarf_rbp_x86_64,
+ gcc_dwarf_rsp_x86_64,
+ // Extended GP Registers
+ gcc_dwarf_r8_x86_64 = 8,
+ gcc_dwarf_r9_x86_64,
+ gcc_dwarf_r10_x86_64,
+ gcc_dwarf_r11_x86_64,
+ gcc_dwarf_r12_x86_64,
+ gcc_dwarf_r13_x86_64,
+ gcc_dwarf_r14_x86_64,
+ gcc_dwarf_r15_x86_64,
+ // Return Address (RA) mapped to RIP
+ gcc_dwarf_rip_x86_64 = 16,
+ // SSE Vector Registers
+ gcc_dwarf_xmm0_x86_64 = 17,
+ gcc_dwarf_xmm1_x86_64,
+ gcc_dwarf_xmm2_x86_64,
+ gcc_dwarf_xmm3_x86_64,
+ gcc_dwarf_xmm4_x86_64,
+ gcc_dwarf_xmm5_x86_64,
+ gcc_dwarf_xmm6_x86_64,
+ gcc_dwarf_xmm7_x86_64,
+ gcc_dwarf_xmm8_x86_64,
+ gcc_dwarf_xmm9_x86_64,
+ gcc_dwarf_xmm10_x86_64,
+ gcc_dwarf_xmm11_x86_64,
+ gcc_dwarf_xmm12_x86_64,
+ gcc_dwarf_xmm13_x86_64,
+ gcc_dwarf_xmm14_x86_64,
+ gcc_dwarf_xmm15_x86_64,
+ // Floating Point Registers
+ gcc_dwarf_st0_x86_64 = 33,
+ gcc_dwarf_st1_x86_64,
+ gcc_dwarf_st2_x86_64,
+ gcc_dwarf_st3_x86_64,
+ gcc_dwarf_st4_x86_64,
+ gcc_dwarf_st5_x86_64,
+ gcc_dwarf_st6_x86_64,
+ gcc_dwarf_st7_x86_64,
+ // MMX Registers
+ gcc_dwarf_mm0_x86_64 = 41,
+ gcc_dwarf_mm1_x86_64,
+ gcc_dwarf_mm2_x86_64,
+ gcc_dwarf_mm3_x86_64,
+ gcc_dwarf_mm4_x86_64,
+ gcc_dwarf_mm5_x86_64,
+ gcc_dwarf_mm6_x86_64,
+ gcc_dwarf_mm7_x86_64,
+ // Control and Status Flags Register
+ gcc_dwarf_rflags_x86_64 = 49,
+ // selector registers
+ gcc_dwarf_es_x86_64 = 50,
+ gcc_dwarf_cs_x86_64,
+ gcc_dwarf_ss_x86_64,
+ gcc_dwarf_ds_x86_64,
+ gcc_dwarf_fs_x86_64,
+ gcc_dwarf_gs_x86_64,
+ // Floating point control registers
+ gcc_dwarf_mxcsr_x86_64 = 64, // Media Control and Status
+ gcc_dwarf_fctrl_x86_64, // x87 control word
+ gcc_dwarf_fstat_x86_64, // x87 status word
+ // Upper Vector Registers
+ gcc_dwarf_ymm0h_x86_64 = 67,
+ gcc_dwarf_ymm1h_x86_64,
+ gcc_dwarf_ymm2h_x86_64,
+ gcc_dwarf_ymm3h_x86_64,
+ gcc_dwarf_ymm4h_x86_64,
+ gcc_dwarf_ymm5h_x86_64,
+ gcc_dwarf_ymm6h_x86_64,
+ gcc_dwarf_ymm7h_x86_64,
+ gcc_dwarf_ymm8h_x86_64,
+ gcc_dwarf_ymm9h_x86_64,
+ gcc_dwarf_ymm10h_x86_64,
+ gcc_dwarf_ymm11h_x86_64,
+ gcc_dwarf_ymm12h_x86_64,
+ gcc_dwarf_ymm13h_x86_64,
+ gcc_dwarf_ymm14h_x86_64,
+ gcc_dwarf_ymm15h_x86_64,
+ // AVX2 Vector Mask Registers
+ // gcc_dwarf_k0_x86_64 = 118,
+ // gcc_dwarf_k1_x86_64,
+ // gcc_dwarf_k2_x86_64,
+ // gcc_dwarf_k3_x86_64,
+ // gcc_dwarf_k4_x86_64,
+ // gcc_dwarf_k5_x86_64,
+ // gcc_dwarf_k6_x86_64,
+ // gcc_dwarf_k7_x86_64,
+};
+
+// GDB Register numbers (eRegisterKindGDB)
+enum
+{
+ // GP Registers
+ gdb_rax_x86_64 = 0,
+ gdb_rbx_x86_64,
+ gdb_rcx_x86_64,
+ gdb_rdx_x86_64,
+ gdb_rsi_x86_64,
+ gdb_rdi_x86_64,
+ gdb_rbp_x86_64,
+ gdb_rsp_x86_64,
+ // Extended GP Registers
+ gdb_r8_x86_64,
+ gdb_r9_x86_64,
+ gdb_r10_x86_64,
+ gdb_r11_x86_64,
+ gdb_r12_x86_64,
+ gdb_r13_x86_64,
+ gdb_r14_x86_64,
+ gdb_r15_x86_64,
+ // Return Address (RA) mapped to RIP
+ gdb_rip_x86_64,
+ // Control and Status Flags Register
+ gdb_rflags_x86_64,
+ gdb_cs_x86_64,
+ gdb_ss_x86_64,
+ gdb_ds_x86_64,
+ gdb_es_x86_64,
+ gdb_fs_x86_64,
+ gdb_gs_x86_64,
+ // Floating Point Registers
+ gdb_st0_x86_64,
+ gdb_st1_x86_64,
+ gdb_st2_x86_64,
+ gdb_st3_x86_64,
+ gdb_st4_x86_64,
+ gdb_st5_x86_64,
+ gdb_st6_x86_64,
+ gdb_st7_x86_64,
+ gdb_fctrl_x86_64,
+ gdb_fstat_x86_64,
+ gdb_ftag_x86_64,
+ gdb_fiseg_x86_64,
+ gdb_fioff_x86_64,
+ gdb_foseg_x86_64,
+ gdb_fooff_x86_64,
+ gdb_fop_x86_64,
+ // SSE Vector Registers
+ gdb_xmm0_x86_64 = 40,
+ gdb_xmm1_x86_64,
+ gdb_xmm2_x86_64,
+ gdb_xmm3_x86_64,
+ gdb_xmm4_x86_64,
+ gdb_xmm5_x86_64,
+ gdb_xmm6_x86_64,
+ gdb_xmm7_x86_64,
+ gdb_xmm8_x86_64,
+ gdb_xmm9_x86_64,
+ gdb_xmm10_x86_64,
+ gdb_xmm11_x86_64,
+ gdb_xmm12_x86_64,
+ gdb_xmm13_x86_64,
+ gdb_xmm14_x86_64,
+ gdb_xmm15_x86_64,
+ // Floating point control registers
+ gdb_mxcsr_x86_64 = 56,
+ gdb_ymm0h_x86_64,
+ gdb_ymm1h_x86_64,
+ gdb_ymm2h_x86_64,
+ gdb_ymm3h_x86_64,
+ gdb_ymm4h_x86_64,
+ gdb_ymm5h_x86_64,
+ gdb_ymm6h_x86_64,
+ gdb_ymm7h_x86_64,
+ gdb_ymm8h_x86_64,
+ gdb_ymm9h_x86_64,
+ gdb_ymm10h_x86_64,
+ gdb_ymm11h_x86_64,
+ gdb_ymm12h_x86_64,
+ gdb_ymm13h_x86_64,
+ gdb_ymm14h_x86_64,
+ gdb_ymm15h_x86_64
+};
+
+//---------------------------------------------------------------------------
+// Generic floating-point registers
+//---------------------------------------------------------------------------
+
+struct MMSReg
+{
+ uint8_t bytes[10];
+ uint8_t pad[6];
+};
+
+struct XMMReg
+{
+ uint8_t bytes[16]; // 128-bits for each XMM register
+};
+
+// i387_fxsave_struct
+struct FXSAVE
+{
+ 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;
+ } 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[16]; // 16*16 bytes for each XMM-reg = 256 bytes
+ uint32_t padding[24];
+};
+
+//---------------------------------------------------------------------------
+// Extended floating-point registers
+//---------------------------------------------------------------------------
+
+struct YMMHReg
+{
+ uint8_t bytes[16]; // 16 * 8 bits for the high bytes of each YMM register
+};
+
+struct YMMReg
+{
+ uint8_t bytes[32]; // 16 * 16 bits for each YMM register
+};
+
+struct YMM
+{
+ YMMReg ymm[16]; // assembled from ymmh and xmm registers
+};
+
+struct XSAVE_HDR
+{
+ uint64_t xstate_bv; // OS enabled xstate mask to determine the extended states supported by the processor
+ uint64_t reserved1[2];
+ uint64_t reserved2[5];
+} __attribute__((packed));
+
+// x86 extensions to FXSAVE (i.e. for AVX processors)
+struct XSAVE
+{
+ FXSAVE i387; // floating point registers typical in i387_fxsave_struct
+ XSAVE_HDR header; // The xsave_hdr_struct can be used to determine if the following extensions are usable
+ YMMHReg ymmh[16]; // High 16 bytes of each of 16 YMM registers (the low bytes are in FXSAVE.xmm for compatibility with SSE)
+ // Slot any extensions to the register file here
+} __attribute__((packed, aligned (64)));
+
+// Floating-point registers
+struct FPR
+{
+ // Thread state for the floating-point unit of the processor read by ptrace.
+ union XSTATE
+ {
+ FXSAVE fxsave; // Generic floating-point registers.
+ XSAVE xsave; // x86 extended processor state.
+ } xstate;
+};
+
+//---------------------------------------------------------------------------
+// ptrace PTRACE_GETREGSET, PTRACE_SETREGSET structure
+//---------------------------------------------------------------------------
+
+struct IOVEC
+{
+ void *iov_base; // pointer to XSAVE
+ size_t iov_len; // sizeof(XSAVE)
};
#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
deleted file mode 100644
index 617b18484e5a..000000000000
--- a/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
+++ /dev/null
@@ -1,1563 +0,0 @@
-//===-- RegisterContext_x86_64.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 "ProcessPOSIX.h"
-#if defined(__linux__) or defined(__FreeBSD__)
-#include "ProcessMonitor.h"
-#endif
-#include "RegisterContext_i386.h"
-#include "RegisterContext_x86.h"
-#include "RegisterContext_x86_64.h"
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-// Support ptrace extensions even when compiled without required kernel support
-#ifndef NT_X86_XSTATE
- #define NT_X86_XSTATE 0x202
-#endif
-
-enum
-{
- gcc_dwarf_gpr_rax = 0,
- gcc_dwarf_gpr_rdx,
- gcc_dwarf_gpr_rcx,
- gcc_dwarf_gpr_rbx,
- gcc_dwarf_gpr_rsi,
- gcc_dwarf_gpr_rdi,
- gcc_dwarf_gpr_rbp,
- gcc_dwarf_gpr_rsp,
- gcc_dwarf_gpr_r8,
- gcc_dwarf_gpr_r9,
- gcc_dwarf_gpr_r10,
- gcc_dwarf_gpr_r11,
- gcc_dwarf_gpr_r12,
- gcc_dwarf_gpr_r13,
- gcc_dwarf_gpr_r14,
- gcc_dwarf_gpr_r15,
- gcc_dwarf_gpr_rip,
- gcc_dwarf_fpu_xmm0,
- gcc_dwarf_fpu_xmm1,
- gcc_dwarf_fpu_xmm2,
- gcc_dwarf_fpu_xmm3,
- gcc_dwarf_fpu_xmm4,
- gcc_dwarf_fpu_xmm5,
- gcc_dwarf_fpu_xmm6,
- gcc_dwarf_fpu_xmm7,
- gcc_dwarf_fpu_xmm8,
- gcc_dwarf_fpu_xmm9,
- gcc_dwarf_fpu_xmm10,
- gcc_dwarf_fpu_xmm11,
- gcc_dwarf_fpu_xmm12,
- gcc_dwarf_fpu_xmm13,
- gcc_dwarf_fpu_xmm14,
- gcc_dwarf_fpu_xmm15,
- gcc_dwarf_fpu_stmm0,
- gcc_dwarf_fpu_stmm1,
- gcc_dwarf_fpu_stmm2,
- gcc_dwarf_fpu_stmm3,
- gcc_dwarf_fpu_stmm4,
- gcc_dwarf_fpu_stmm5,
- gcc_dwarf_fpu_stmm6,
- gcc_dwarf_fpu_stmm7,
- gcc_dwarf_fpu_ymm0,
- gcc_dwarf_fpu_ymm1,
- gcc_dwarf_fpu_ymm2,
- gcc_dwarf_fpu_ymm3,
- gcc_dwarf_fpu_ymm4,
- gcc_dwarf_fpu_ymm5,
- gcc_dwarf_fpu_ymm6,
- gcc_dwarf_fpu_ymm7,
- gcc_dwarf_fpu_ymm8,
- gcc_dwarf_fpu_ymm9,
- gcc_dwarf_fpu_ymm10,
- gcc_dwarf_fpu_ymm11,
- gcc_dwarf_fpu_ymm12,
- gcc_dwarf_fpu_ymm13,
- gcc_dwarf_fpu_ymm14,
- gcc_dwarf_fpu_ymm15
-};
-
-enum
-{
- gdb_gpr_rax = 0,
- gdb_gpr_rbx = 1,
- gdb_gpr_rcx = 2,
- gdb_gpr_rdx = 3,
- gdb_gpr_rsi = 4,
- gdb_gpr_rdi = 5,
- gdb_gpr_rbp = 6,
- gdb_gpr_rsp = 7,
- gdb_gpr_r8 = 8,
- gdb_gpr_r9 = 9,
- gdb_gpr_r10 = 10,
- gdb_gpr_r11 = 11,
- gdb_gpr_r12 = 12,
- gdb_gpr_r13 = 13,
- gdb_gpr_r14 = 14,
- gdb_gpr_r15 = 15,
- gdb_gpr_rip = 16,
- gdb_gpr_rflags = 17,
- gdb_gpr_cs = 18,
- gdb_gpr_ss = 19,
- gdb_gpr_ds = 20,
- gdb_gpr_es = 21,
- gdb_gpr_fs = 22,
- gdb_gpr_gs = 23,
- gdb_fpu_stmm0 = 24,
- gdb_fpu_stmm1 = 25,
- gdb_fpu_stmm2 = 26,
- gdb_fpu_stmm3 = 27,
- gdb_fpu_stmm4 = 28,
- gdb_fpu_stmm5 = 29,
- gdb_fpu_stmm6 = 30,
- gdb_fpu_stmm7 = 31,
- gdb_fpu_fcw = 32,
- gdb_fpu_fsw = 33,
- gdb_fpu_ftw = 34,
- gdb_fpu_cs_64 = 35,
- gdb_fpu_ip = 36,
- gdb_fpu_ds_64 = 37,
- gdb_fpu_dp = 38,
- gdb_fpu_fop = 39,
- gdb_fpu_xmm0 = 40,
- gdb_fpu_xmm1 = 41,
- gdb_fpu_xmm2 = 42,
- gdb_fpu_xmm3 = 43,
- gdb_fpu_xmm4 = 44,
- gdb_fpu_xmm5 = 45,
- gdb_fpu_xmm6 = 46,
- gdb_fpu_xmm7 = 47,
- gdb_fpu_xmm8 = 48,
- gdb_fpu_xmm9 = 49,
- gdb_fpu_xmm10 = 50,
- gdb_fpu_xmm11 = 51,
- gdb_fpu_xmm12 = 52,
- gdb_fpu_xmm13 = 53,
- gdb_fpu_xmm14 = 54,
- gdb_fpu_xmm15 = 55,
- gdb_fpu_mxcsr = 56,
- gdb_fpu_ymm0 = 57,
- gdb_fpu_ymm1 = 58,
- gdb_fpu_ymm2 = 59,
- gdb_fpu_ymm3 = 60,
- gdb_fpu_ymm4 = 61,
- gdb_fpu_ymm5 = 62,
- gdb_fpu_ymm6 = 63,
- gdb_fpu_ymm7 = 64,
- gdb_fpu_ymm8 = 65,
- gdb_fpu_ymm9 = 66,
- gdb_fpu_ymm10 = 67,
- gdb_fpu_ymm11 = 68,
- gdb_fpu_ymm12 = 69,
- gdb_fpu_ymm13 = 70,
- gdb_fpu_ymm14 = 71,
- gdb_fpu_ymm15 = 72
-};
-
-static const
-uint32_t g_gpr_regnums[k_num_gpr_registers] =
-{
- gpr_rax,
- gpr_rbx,
- gpr_rcx,
- gpr_rdx,
- gpr_rdi,
- gpr_rsi,
- gpr_rbp,
- gpr_rsp,
- gpr_r8,
- gpr_r9,
- gpr_r10,
- gpr_r11,
- gpr_r12,
- gpr_r13,
- gpr_r14,
- gpr_r15,
- gpr_rip,
- gpr_rflags,
- gpr_cs,
- gpr_fs,
- gpr_gs,
- gpr_ss,
- gpr_ds,
- gpr_es,
- gpr_eax,
- gpr_ebx,
- gpr_ecx,
- gpr_edx,
- gpr_edi,
- gpr_esi,
- gpr_ebp,
- gpr_esp,
- gpr_eip,
- gpr_eflags
-};
-
-static const uint32_t
-g_fpu_regnums[k_num_fpr_registers] =
-{
- fpu_fcw,
- fpu_fsw,
- fpu_ftw,
- fpu_fop,
- fpu_ip,
- fpu_cs,
- fpu_dp,
- fpu_ds,
- fpu_mxcsr,
- fpu_mxcsrmask,
- fpu_stmm0,
- fpu_stmm1,
- fpu_stmm2,
- fpu_stmm3,
- fpu_stmm4,
- fpu_stmm5,
- fpu_stmm6,
- fpu_stmm7,
- fpu_xmm0,
- fpu_xmm1,
- fpu_xmm2,
- fpu_xmm3,
- fpu_xmm4,
- fpu_xmm5,
- fpu_xmm6,
- fpu_xmm7,
- fpu_xmm8,
- fpu_xmm9,
- fpu_xmm10,
- fpu_xmm11,
- fpu_xmm12,
- fpu_xmm13,
- fpu_xmm14,
- fpu_xmm15
-};
-
-static const uint32_t
-g_avx_regnums[k_num_avx_registers] =
-{
- fpu_ymm0,
- fpu_ymm1,
- fpu_ymm2,
- fpu_ymm3,
- fpu_ymm4,
- fpu_ymm5,
- fpu_ymm6,
- fpu_ymm7,
- fpu_ymm8,
- fpu_ymm9,
- fpu_ymm10,
- fpu_ymm11,
- fpu_ymm12,
- fpu_ymm13,
- fpu_ymm14,
- fpu_ymm15
-};
-
-// Number of register sets provided by this context.
-enum
-{
- k_num_extended_register_sets = 1,
- k_num_register_sets = 3
-};
-
-static const RegisterSet
-g_reg_sets[k_num_register_sets] =
-{
- { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
- { "Floating Point Registers", "fpu", k_num_fpr_registers, g_fpu_regnums },
- { "Advanced Vector Extensions", "avx", k_num_avx_registers, g_avx_regnums }
-};
-
-// Computes the offset of the given FPR in the extended data area.
-#define FPR_OFFSET(regname) \
- (offsetof(RegisterContext_x86_64::FPR, xstate) + \
- offsetof(RegisterContext_x86_64::FXSAVE, regname))
-
-// Computes the offset of the YMM register assembled from register halves.
-#define YMM_OFFSET(regname) \
- (offsetof(RegisterContext_x86_64::YMM, regname))
-
-// Number of bytes needed to represent a i386 GPR
-#define GPR_i386_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg)
-
-// Number of bytes needed to represent a FPR.
-#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FXSAVE*)NULL)->reg)
-
-// Number of bytes needed to represent the i'th FP register.
-#define FP_SIZE sizeof(((RegisterContext_x86_64::MMSReg*)NULL)->bytes)
-
-// Number of bytes needed to represent an XMM register.
-#define XMM_SIZE sizeof(RegisterContext_x86_64::XMMReg)
-
-// Number of bytes needed to represent a YMM register.
-#define YMM_SIZE sizeof(RegisterContext_x86_64::YMMReg)
-
-// Note that the size and offset will be updated by platform-specific classes.
-#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
- { #reg, alt, 0, 0, eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg }, NULL, NULL }
-
-// Dummy data for RegisterInfo::value_regs as expected by DumpRegisterSet.
-static uint32_t value_regs = LLDB_INVALID_REGNUM;
-
-#define DEFINE_GPR_i386(reg_i386, reg_x86_64, alt, kind1, kind2, kind3, kind4) \
- { #reg_i386, alt, GPR_i386_SIZE(reg_i386), 0, eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg_i386 }, &value_regs, NULL }
-
-#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \
- { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg }, NULL, NULL }
-
-#define DEFINE_FP(reg, i) \
- { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
- eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \
- LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL }
-
-#define DEFINE_XMM(reg, i) \
- { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
- eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \
- LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL }
-
-#define DEFINE_YMM(reg, i) \
- { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(reg[i]), \
- eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \
- LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL }
-
-#define DEFINE_DR(reg, i) \
- { #reg#i, NULL, 0, 0, eEncodingUint, eFormatHex, \
- { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
-
-#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(RegisterContext_x86_64::FPR))
-
-static RegisterInfo
-g_register_infos[k_num_registers] =
-{
- // General purpose registers.
- DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax),
- DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx),
- DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx),
- DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx),
- DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi),
- DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi),
- DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp),
- DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp),
- DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8),
- DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9),
- DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10),
- DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11),
- DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12),
- DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13),
- DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14),
- DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15),
- DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip),
- DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags),
- DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs),
- DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs),
- DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs),
- DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss),
- DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds),
- DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es),
- // i386 registers
- DEFINE_GPR_i386(eax, rax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax),
- DEFINE_GPR_i386(ebx, rbx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx),
- DEFINE_GPR_i386(ecx, rcx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx),
- DEFINE_GPR_i386(edx, rdx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx),
- DEFINE_GPR_i386(edi, rdi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi),
- DEFINE_GPR_i386(esi, rsi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi),
- DEFINE_GPR_i386(ebp, rbp, "fp", gcc_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, gdb_ebp),
- DEFINE_GPR_i386(esp, rsp, "sp", gcc_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, gdb_esp),
- DEFINE_GPR_i386(eip, rip, "pc", gcc_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, gdb_eip),
- DEFINE_GPR_i386(eflags, rflags, "flags", gcc_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS, gdb_eflags),
- // i387 Floating point registers.
- DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw),
- DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw),
- DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw),
- DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop),
- DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip),
- // FIXME: Extract segment from ip.
- DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs_64),
- DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp),
- // FIXME: Extract segment from dp.
- DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds_64),
- DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr),
- DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
-
- // FP registers.
- DEFINE_FP(stmm, 0),
- DEFINE_FP(stmm, 1),
- DEFINE_FP(stmm, 2),
- DEFINE_FP(stmm, 3),
- DEFINE_FP(stmm, 4),
- DEFINE_FP(stmm, 5),
- DEFINE_FP(stmm, 6),
- DEFINE_FP(stmm, 7),
-
- // XMM registers
- DEFINE_XMM(xmm, 0),
- DEFINE_XMM(xmm, 1),
- DEFINE_XMM(xmm, 2),
- DEFINE_XMM(xmm, 3),
- DEFINE_XMM(xmm, 4),
- DEFINE_XMM(xmm, 5),
- DEFINE_XMM(xmm, 6),
- DEFINE_XMM(xmm, 7),
- DEFINE_XMM(xmm, 8),
- DEFINE_XMM(xmm, 9),
- DEFINE_XMM(xmm, 10),
- DEFINE_XMM(xmm, 11),
- DEFINE_XMM(xmm, 12),
- DEFINE_XMM(xmm, 13),
- DEFINE_XMM(xmm, 14),
- DEFINE_XMM(xmm, 15),
-
- // Copy of YMM registers assembled from xmm and ymmh
- DEFINE_YMM(ymm, 0),
- DEFINE_YMM(ymm, 1),
- DEFINE_YMM(ymm, 2),
- DEFINE_YMM(ymm, 3),
- DEFINE_YMM(ymm, 4),
- DEFINE_YMM(ymm, 5),
- DEFINE_YMM(ymm, 6),
- DEFINE_YMM(ymm, 7),
- DEFINE_YMM(ymm, 8),
- DEFINE_YMM(ymm, 9),
- DEFINE_YMM(ymm, 10),
- DEFINE_YMM(ymm, 11),
- DEFINE_YMM(ymm, 12),
- DEFINE_YMM(ymm, 13),
- DEFINE_YMM(ymm, 14),
- DEFINE_YMM(ymm, 15),
-
- // Debug registers for lldb internal use
- DEFINE_DR(dr, 0),
- DEFINE_DR(dr, 1),
- DEFINE_DR(dr, 2),
- DEFINE_DR(dr, 3),
- DEFINE_DR(dr, 4),
- DEFINE_DR(dr, 5),
- DEFINE_DR(dr, 6),
- DEFINE_DR(dr, 7)
-};
-
-static bool IsGPR(unsigned reg)
-{
- return reg <= k_last_gpr; // GPR's come first.
-}
-
-static bool IsAVX(unsigned reg)
-{
- return (k_first_avx <= reg && reg <= k_last_avx);
-}
-static bool IsFPR(unsigned reg)
-{
- return (k_first_fpr <= reg && reg <= k_last_fpr);
-}
-
-
-bool RegisterContext_x86_64::IsFPR(unsigned reg, FPRType fpr_type)
-{
- bool generic_fpr = ::IsFPR(reg);
- if (fpr_type == eXSAVE)
- return generic_fpr || IsAVX(reg);
-
- return generic_fpr;
-}
-
-RegisterContext_x86_64::RegisterContext_x86_64(Thread &thread,
- uint32_t concrete_frame_idx)
- : RegisterContextPOSIX(thread, concrete_frame_idx)
-{
- // Initialize m_iovec to point to the buffer and buffer size
- // using the conventions of Berkeley style UIO structures, as required
- // by PTRACE extensions.
- m_iovec.iov_base = &m_fpr.xstate.xsave;
- m_iovec.iov_len = sizeof(m_fpr.xstate.xsave);
-
- ::memset(&m_fpr, 0, sizeof(RegisterContext_x86_64::FPR));
-
- // elf-core yet to support ReadFPR()
- ProcessSP base = CalculateProcess();
- if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return;
-
- // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx
- m_fpr_type = eXSAVE; // extended floating-point registers, if available
- if (false == ReadFPR())
- m_fpr_type = eFXSAVE; // assume generic floating-point registers
-}
-
-RegisterContext_x86_64::~RegisterContext_x86_64()
-{
-}
-
-void
-RegisterContext_x86_64::Invalidate()
-{
-}
-
-void
-RegisterContext_x86_64::InvalidateAllRegisters()
-{
-}
-
-unsigned
-RegisterContext_x86_64::GetRegisterOffset(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register number.");
- return GetRegisterInfo()[reg].byte_offset;
-}
-
-unsigned
-RegisterContext_x86_64::GetRegisterSize(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register number.");
- return GetRegisterInfo()[reg].byte_size;
-}
-
-size_t
-RegisterContext_x86_64::GetRegisterCount()
-{
- size_t num_registers = k_num_gpr_registers + k_num_fpr_registers;
- if (m_fpr_type == eXSAVE)
- return num_registers + k_num_avx_registers;
- return num_registers;
-}
-
-const RegisterInfo *
-RegisterContext_x86_64::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 g_register_infos;
-}
-
-const RegisterInfo *
-RegisterContext_x86_64::GetRegisterInfoAtIndex(size_t reg)
-{
- if (reg < k_num_registers)
- return &GetRegisterInfo()[reg];
- else
- return NULL;
-}
-
-size_t
-RegisterContext_x86_64::GetRegisterSetCount()
-{
- size_t sets = 0;
- for (size_t set = 0; set < k_num_register_sets; ++set)
- if (IsRegisterSetAvailable(set))
- ++sets;
-
- return sets;
-}
-
-const RegisterSet *
-RegisterContext_x86_64::GetRegisterSet(size_t set)
-{
- if (IsRegisterSetAvailable(set))
- return &g_reg_sets[set];
- else
- return NULL;
-}
-
-unsigned
-RegisterContext_x86_64::GetRegisterIndexFromOffset(unsigned offset)
-{
- unsigned reg;
- for (reg = 0; reg < k_num_registers; reg++)
- {
- if (GetRegisterInfo()[reg].byte_offset == offset)
- break;
- }
- assert(reg < k_num_registers && "Invalid register offset.");
- return reg;
-}
-
-const char *
-RegisterContext_x86_64::GetRegisterName(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register offset.");
- return GetRegisterInfo()[reg].name;
-}
-
-lldb::ByteOrder
-RegisterContext_x86_64::GetByteOrder()
-{
- // Get the target process whose privileged thread was used for the register read.
- lldb::ByteOrder byte_order = eByteOrderInvalid;
- Process *process = CalculateProcess().get();
-
- if (process)
- byte_order = process->GetByteOrder();
- return byte_order;
-}
-
-// Parse ymm registers and into xmm.bytes and ymmh.bytes.
-bool RegisterContext_x86_64::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order)
-{
- if (!IsAVX(reg))
- return false;
-
- if (byte_order == eByteOrderLittle) {
- ::memcpy(m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
- m_ymm_set.ymm[reg - fpu_ymm0].bytes,
- sizeof(RegisterContext_x86_64::XMMReg));
- ::memcpy(m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
- m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
- sizeof(RegisterContext_x86_64::YMMHReg));
- return true;
- }
-
- if (byte_order == eByteOrderBig) {
- ::memcpy(m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
- m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
- sizeof(RegisterContext_x86_64::XMMReg));
- ::memcpy(m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
- m_ymm_set.ymm[reg - fpu_ymm0].bytes,
- sizeof(RegisterContext_x86_64::YMMHReg));
- return true;
- }
- return false; // unsupported or invalid byte order
-}
-
-// Concatenate xmm.bytes with ymmh.bytes
-bool RegisterContext_x86_64::CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order)
-{
- if (!IsAVX(reg))
- return false;
-
- if (byte_order == eByteOrderLittle) {
- ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes,
- m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
- sizeof(RegisterContext_x86_64::XMMReg));
- ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
- m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
- sizeof(RegisterContext_x86_64::YMMHReg));
- return true;
- }
- if (byte_order == eByteOrderBig) {
- ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
- m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
- sizeof(RegisterContext_x86_64::XMMReg));
- ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes,
- m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
- sizeof(RegisterContext_x86_64::YMMHReg));
- return true;
- }
- return false; // unsupported or invalid byte order
-}
-
-bool
-RegisterContext_x86_64::IsRegisterSetAvailable(size_t set_index)
-{
- // Note: Extended register sets are assumed to be at the end of g_reg_sets...
- size_t num_sets = k_num_register_sets - k_num_extended_register_sets;
- if (m_fpr_type == eXSAVE) // ...and to start with AVX registers.
- ++num_sets;
-
- return (set_index < num_sets);
-}
-
-bool
-RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
-{
- if (!reg_info)
- return false;
-
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsFPR(reg, m_fpr_type)) {
- if (!ReadFPR())
- return false;
- }
- else {
- bool success = ReadRegister(reg, value);
-
- // If an i386 register should be parsed from an x86_64 register...
- if (success && reg >= k_first_i386 && reg <= k_last_i386)
- if (value.GetByteSize() > reg_info->byte_size)
- value.SetType(reg_info); // ...use the type specified by reg_info rather than the uint64_t default
- return success;
- }
-
- if (reg_info->encoding == eEncodingVector) {
- ByteOrder byte_order = GetByteOrder();
-
- if (byte_order != ByteOrder::eByteOrderInvalid) {
- if (reg >= fpu_stmm0 && reg <= fpu_stmm7) {
- value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, byte_order);
- }
- if (reg >= fpu_xmm0 && reg <= fpu_xmm15) {
- value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, byte_order);
- }
- if (reg >= fpu_ymm0 && reg <= fpu_ymm15) {
- // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
- if (m_fpr_type == eXSAVE && CopyXSTATEtoYMM(reg, byte_order))
- value.SetBytes(m_ymm_set.ymm[reg - fpu_ymm0].bytes, reg_info->byte_size, byte_order);
- else
- return false;
- }
- return value.GetType() == RegisterValue::eTypeBytes;
- }
- return false;
- }
-
- // Note that lldb uses slightly different naming conventions from sys/user.h
- switch (reg)
- {
- default:
- return false;
- case fpu_dp:
- value = m_fpr.xstate.fxsave.dp;
- break;
- case fpu_fcw:
- value = m_fpr.xstate.fxsave.fcw;
- break;
- case fpu_fsw:
- value = m_fpr.xstate.fxsave.fsw;
- break;
- case fpu_ip:
- value = m_fpr.xstate.fxsave.ip;
- break;
- case fpu_fop:
- value = m_fpr.xstate.fxsave.fop;
- break;
- case fpu_ftw:
- value = m_fpr.xstate.fxsave.ftw;
- break;
- case fpu_mxcsr:
- value = m_fpr.xstate.fxsave.mxcsr;
- break;
- case fpu_mxcsrmask:
- value = m_fpr.xstate.fxsave.mxcsrmask;
- break;
- }
- return true;
-}
-
-bool
-RegisterContext_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp)
-{
- bool success = false;
- data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
- if (data_sp && ReadGPR () && ReadFPR ())
- {
- uint8_t *dst = data_sp->GetBytes();
- success = dst != 0;
-
- if (success) {
- ::memcpy (dst, &m_gpr, GetGPRSize());
- dst += GetGPRSize();
- }
- if (m_fpr_type == eFXSAVE)
- ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
-
- if (m_fpr_type == eXSAVE) {
- ByteOrder byte_order = GetByteOrder();
-
- // Assemble the YMM register content from the register halves.
- for (uint32_t reg = fpu_ymm0; success && reg <= fpu_ymm15; ++reg)
- success = CopyXSTATEtoYMM(reg, byte_order);
-
- if (success) {
- // Copy the extended register state including the assembled ymm registers.
- ::memcpy (dst, &m_fpr, sizeof(m_fpr));
- }
- }
- }
- return success;
-}
-
-bool
-RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value)
-{
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- if (IsGPR(reg)) {
- return WriteRegister(reg, value);
- }
-
- if (IsFPR(reg, m_fpr_type)) {
- switch (reg)
- {
- default:
- if (reg_info->encoding != eEncodingVector)
- return false;
-
- if (reg >= fpu_stmm0 && reg <= fpu_stmm7)
- ::memcpy (m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize());
-
- if (reg >= fpu_xmm0 && reg <= fpu_xmm15)
- ::memcpy (m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize());
-
- if (reg >= fpu_ymm0 && reg <= fpu_ymm15) {
- if (m_fpr_type != eXSAVE)
- return false; // the target processor does not support AVX
-
- // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes
- ::memcpy (m_ymm_set.ymm[reg - fpu_ymm0].bytes, value.GetBytes(), value.GetByteSize());
- if (false == CopyYMMtoXSTATE(reg, GetByteOrder()))
- return false;
- }
- break;
- case fpu_dp:
- m_fpr.xstate.fxsave.dp = value.GetAsUInt64();
- break;
- case fpu_fcw:
- m_fpr.xstate.fxsave.fcw = value.GetAsUInt16();
- break;
- case fpu_fsw:
- m_fpr.xstate.fxsave.fsw = value.GetAsUInt16();
- break;
- case fpu_ip:
- m_fpr.xstate.fxsave.ip = value.GetAsUInt64();
- break;
- case fpu_fop:
- m_fpr.xstate.fxsave.fop = value.GetAsUInt16();
- break;
- case fpu_ftw:
- m_fpr.xstate.fxsave.ftw = value.GetAsUInt16();
- break;
- case fpu_mxcsr:
- m_fpr.xstate.fxsave.mxcsr = value.GetAsUInt32();
- break;
- case fpu_mxcsrmask:
- m_fpr.xstate.fxsave.mxcsrmask = value.GetAsUInt32();
- break;
- }
- if (WriteFPR()) {
- if (IsAVX(reg))
- return CopyYMMtoXSTATE(reg, GetByteOrder());
- return true;
- }
- }
- return false;
-}
-
-bool
-RegisterContext_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp)
-{
- bool success = false;
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
- {
- uint8_t *src = data_sp->GetBytes();
- if (src) {
- ::memcpy (&m_gpr, src, GetGPRSize());
-
- if (WriteGPR()) {
- src += GetGPRSize();
- if (m_fpr_type == eFXSAVE)
- ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
- if (m_fpr_type == eXSAVE)
- ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
-
- success = WriteFPR();
- if (success) {
- success = true;
-
- if (m_fpr_type == eXSAVE) {
- ByteOrder byte_order = GetByteOrder();
-
- // Parse the YMM register content from the register halves.
- for (uint32_t reg = fpu_ymm0; success && reg <= fpu_ymm15; ++reg)
- success = CopyYMMtoXSTATE(reg, byte_order);
- }
- }
- }
- }
- }
- return success;
-}
-
-bool
-RegisterContext_x86_64::UpdateAfterBreakpoint()
-{
- // PC points one byte past the int3 responsible for the breakpoint.
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- SetPC(pc - 1);
- return true;
-}
-
-uint32_t
-RegisterContext_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind,
- uint32_t num)
-{
- const Process *process = CalculateProcess().get();
- if (process)
- {
- const ArchSpec arch = process->GetTarget().GetArchitecture();;
- switch (arch.GetCore())
- {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- {
- if (kind == eRegisterKindGeneric)
- {
- switch (num)
- {
- case LLDB_REGNUM_GENERIC_PC: return gpr_eip;
- case LLDB_REGNUM_GENERIC_SP: return gpr_esp;
- case LLDB_REGNUM_GENERIC_FP: return gpr_ebp;
- case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags;
- case LLDB_REGNUM_GENERIC_RA:
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
- {
- switch (num)
- {
- case dwarf_eax: return gpr_eax;
- case dwarf_edx: return gpr_edx;
- case dwarf_ecx: return gpr_ecx;
- case dwarf_ebx: return gpr_ebx;
- case dwarf_esi: return gpr_esi;
- case dwarf_edi: return gpr_edi;
- case dwarf_ebp: return gpr_ebp;
- case dwarf_esp: return gpr_esp;
- case dwarf_eip: return gpr_eip;
- case dwarf_xmm0: return fpu_xmm0;
- case dwarf_xmm1: return fpu_xmm1;
- case dwarf_xmm2: return fpu_xmm2;
- case dwarf_xmm3: return fpu_xmm3;
- case dwarf_xmm4: return fpu_xmm4;
- case dwarf_xmm5: return fpu_xmm5;
- case dwarf_xmm6: return fpu_xmm6;
- case dwarf_xmm7: return fpu_xmm7;
- case dwarf_stmm0: return fpu_stmm0;
- case dwarf_stmm1: return fpu_stmm1;
- case dwarf_stmm2: return fpu_stmm2;
- case dwarf_stmm3: return fpu_stmm3;
- case dwarf_stmm4: return fpu_stmm4;
- case dwarf_stmm5: return fpu_stmm5;
- case dwarf_stmm6: return fpu_stmm6;
- case dwarf_stmm7: return fpu_stmm7;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGDB)
- {
- switch (num)
- {
- case gdb_eax : return gpr_eax;
- case gdb_ebx : return gpr_ebx;
- case gdb_ecx : return gpr_ecx;
- case gdb_edx : return gpr_edx;
- case gdb_esi : return gpr_esi;
- case gdb_edi : return gpr_edi;
- case gdb_ebp : return gpr_ebp;
- case gdb_esp : return gpr_esp;
- case gdb_eip : return gpr_eip;
- case gdb_eflags : return gpr_eflags;
- case gdb_cs : return gpr_cs;
- case gdb_ss : return gpr_ss;
- case gdb_ds : return gpr_ds;
- case gdb_es : return gpr_es;
- case gdb_fs : return gpr_fs;
- case gdb_gs : return gpr_gs;
- case gdb_stmm0 : return fpu_stmm0;
- case gdb_stmm1 : return fpu_stmm1;
- case gdb_stmm2 : return fpu_stmm2;
- case gdb_stmm3 : return fpu_stmm3;
- case gdb_stmm4 : return fpu_stmm4;
- case gdb_stmm5 : return fpu_stmm5;
- case gdb_stmm6 : return fpu_stmm6;
- case gdb_stmm7 : return fpu_stmm7;
- case gdb_fcw : return fpu_fcw;
- case gdb_fsw : return fpu_fsw;
- case gdb_ftw : return fpu_ftw;
- case gdb_fpu_cs : return fpu_cs;
- case gdb_ip : return fpu_ip;
- case gdb_fpu_ds : return fpu_ds; //fpu_fos
- case gdb_dp : return fpu_dp; //fpu_foo
- case gdb_fop : return fpu_fop;
- case gdb_xmm0 : return fpu_xmm0;
- case gdb_xmm1 : return fpu_xmm1;
- case gdb_xmm2 : return fpu_xmm2;
- case gdb_xmm3 : return fpu_xmm3;
- case gdb_xmm4 : return fpu_xmm4;
- case gdb_xmm5 : return fpu_xmm5;
- case gdb_xmm6 : return fpu_xmm6;
- case gdb_xmm7 : return fpu_xmm7;
- case gdb_mxcsr : return fpu_mxcsr;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
- else if (kind == eRegisterKindLLDB)
- {
- return num;
- }
-
- break;
- }
-
- case ArchSpec::eCore_x86_64_x86_64:
- {
- if (kind == eRegisterKindGeneric)
- {
- switch (num)
- {
- case LLDB_REGNUM_GENERIC_PC: return gpr_rip;
- case LLDB_REGNUM_GENERIC_SP: return gpr_rsp;
- case LLDB_REGNUM_GENERIC_FP: return gpr_rbp;
- case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags;
- case LLDB_REGNUM_GENERIC_RA:
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
- {
- switch (num)
- {
- case gcc_dwarf_gpr_rax: return gpr_rax;
- case gcc_dwarf_gpr_rdx: return gpr_rdx;
- case gcc_dwarf_gpr_rcx: return gpr_rcx;
- case gcc_dwarf_gpr_rbx: return gpr_rbx;
- case gcc_dwarf_gpr_rsi: return gpr_rsi;
- case gcc_dwarf_gpr_rdi: return gpr_rdi;
- case gcc_dwarf_gpr_rbp: return gpr_rbp;
- case gcc_dwarf_gpr_rsp: return gpr_rsp;
- case gcc_dwarf_gpr_r8: return gpr_r8;
- case gcc_dwarf_gpr_r9: return gpr_r9;
- case gcc_dwarf_gpr_r10: return gpr_r10;
- case gcc_dwarf_gpr_r11: return gpr_r11;
- case gcc_dwarf_gpr_r12: return gpr_r12;
- case gcc_dwarf_gpr_r13: return gpr_r13;
- case gcc_dwarf_gpr_r14: return gpr_r14;
- case gcc_dwarf_gpr_r15: return gpr_r15;
- case gcc_dwarf_gpr_rip: return gpr_rip;
- case gcc_dwarf_fpu_xmm0: return fpu_xmm0;
- case gcc_dwarf_fpu_xmm1: return fpu_xmm1;
- case gcc_dwarf_fpu_xmm2: return fpu_xmm2;
- case gcc_dwarf_fpu_xmm3: return fpu_xmm3;
- case gcc_dwarf_fpu_xmm4: return fpu_xmm4;
- case gcc_dwarf_fpu_xmm5: return fpu_xmm5;
- case gcc_dwarf_fpu_xmm6: return fpu_xmm6;
- case gcc_dwarf_fpu_xmm7: return fpu_xmm7;
- case gcc_dwarf_fpu_xmm8: return fpu_xmm8;
- case gcc_dwarf_fpu_xmm9: return fpu_xmm9;
- case gcc_dwarf_fpu_xmm10: return fpu_xmm10;
- case gcc_dwarf_fpu_xmm11: return fpu_xmm11;
- case gcc_dwarf_fpu_xmm12: return fpu_xmm12;
- case gcc_dwarf_fpu_xmm13: return fpu_xmm13;
- case gcc_dwarf_fpu_xmm14: return fpu_xmm14;
- case gcc_dwarf_fpu_xmm15: return fpu_xmm15;
- case gcc_dwarf_fpu_stmm0: return fpu_stmm0;
- case gcc_dwarf_fpu_stmm1: return fpu_stmm1;
- case gcc_dwarf_fpu_stmm2: return fpu_stmm2;
- case gcc_dwarf_fpu_stmm3: return fpu_stmm3;
- case gcc_dwarf_fpu_stmm4: return fpu_stmm4;
- case gcc_dwarf_fpu_stmm5: return fpu_stmm5;
- case gcc_dwarf_fpu_stmm6: return fpu_stmm6;
- case gcc_dwarf_fpu_stmm7: return fpu_stmm7;
- case gcc_dwarf_fpu_ymm0: return fpu_ymm0;
- case gcc_dwarf_fpu_ymm1: return fpu_ymm1;
- case gcc_dwarf_fpu_ymm2: return fpu_ymm2;
- case gcc_dwarf_fpu_ymm3: return fpu_ymm3;
- case gcc_dwarf_fpu_ymm4: return fpu_ymm4;
- case gcc_dwarf_fpu_ymm5: return fpu_ymm5;
- case gcc_dwarf_fpu_ymm6: return fpu_ymm6;
- case gcc_dwarf_fpu_ymm7: return fpu_ymm7;
- case gcc_dwarf_fpu_ymm8: return fpu_ymm8;
- case gcc_dwarf_fpu_ymm9: return fpu_ymm9;
- case gcc_dwarf_fpu_ymm10: return fpu_ymm10;
- case gcc_dwarf_fpu_ymm11: return fpu_ymm11;
- case gcc_dwarf_fpu_ymm12: return fpu_ymm12;
- case gcc_dwarf_fpu_ymm13: return fpu_ymm13;
- case gcc_dwarf_fpu_ymm14: return fpu_ymm14;
- case gcc_dwarf_fpu_ymm15: return fpu_ymm15;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGDB)
- {
- switch (num)
- {
- case gdb_gpr_rax : return gpr_rax;
- case gdb_gpr_rbx : return gpr_rbx;
- case gdb_gpr_rcx : return gpr_rcx;
- case gdb_gpr_rdx : return gpr_rdx;
- case gdb_gpr_rsi : return gpr_rsi;
- case gdb_gpr_rdi : return gpr_rdi;
- case gdb_gpr_rbp : return gpr_rbp;
- case gdb_gpr_rsp : return gpr_rsp;
- case gdb_gpr_r8 : return gpr_r8;
- case gdb_gpr_r9 : return gpr_r9;
- case gdb_gpr_r10 : return gpr_r10;
- case gdb_gpr_r11 : return gpr_r11;
- case gdb_gpr_r12 : return gpr_r12;
- case gdb_gpr_r13 : return gpr_r13;
- case gdb_gpr_r14 : return gpr_r14;
- case gdb_gpr_r15 : return gpr_r15;
- case gdb_gpr_rip : return gpr_rip;
- case gdb_gpr_rflags : return gpr_rflags;
- case gdb_gpr_cs : return gpr_cs;
- case gdb_gpr_ss : return gpr_ss;
- case gdb_gpr_ds : return gpr_ds;
- case gdb_gpr_es : return gpr_es;
- case gdb_gpr_fs : return gpr_fs;
- case gdb_gpr_gs : return gpr_gs;
- case gdb_fpu_stmm0 : return fpu_stmm0;
- case gdb_fpu_stmm1 : return fpu_stmm1;
- case gdb_fpu_stmm2 : return fpu_stmm2;
- case gdb_fpu_stmm3 : return fpu_stmm3;
- case gdb_fpu_stmm4 : return fpu_stmm4;
- case gdb_fpu_stmm5 : return fpu_stmm5;
- case gdb_fpu_stmm6 : return fpu_stmm6;
- case gdb_fpu_stmm7 : return fpu_stmm7;
- case gdb_fpu_fcw : return fpu_fcw;
- case gdb_fpu_fsw : return fpu_fsw;
- case gdb_fpu_ftw : return fpu_ftw;
- case gdb_fpu_cs_64 : return fpu_cs;
- case gdb_fpu_ip : return fpu_ip;
- case gdb_fpu_ds_64 : return fpu_ds;
- case gdb_fpu_dp : return fpu_dp;
- case gdb_fpu_fop : return fpu_fop;
- case gdb_fpu_xmm0 : return fpu_xmm0;
- case gdb_fpu_xmm1 : return fpu_xmm1;
- case gdb_fpu_xmm2 : return fpu_xmm2;
- case gdb_fpu_xmm3 : return fpu_xmm3;
- case gdb_fpu_xmm4 : return fpu_xmm4;
- case gdb_fpu_xmm5 : return fpu_xmm5;
- case gdb_fpu_xmm6 : return fpu_xmm6;
- case gdb_fpu_xmm7 : return fpu_xmm7;
- case gdb_fpu_xmm8 : return fpu_xmm8;
- case gdb_fpu_xmm9 : return fpu_xmm9;
- case gdb_fpu_xmm10 : return fpu_xmm10;
- case gdb_fpu_xmm11 : return fpu_xmm11;
- case gdb_fpu_xmm12 : return fpu_xmm12;
- case gdb_fpu_xmm13 : return fpu_xmm13;
- case gdb_fpu_xmm14 : return fpu_xmm14;
- case gdb_fpu_xmm15 : return fpu_xmm15;
- case gdb_fpu_mxcsr : return fpu_mxcsr;
- case gdb_fpu_ymm0 : return fpu_ymm0;
- case gdb_fpu_ymm1 : return fpu_ymm1;
- case gdb_fpu_ymm2 : return fpu_ymm2;
- case gdb_fpu_ymm3 : return fpu_ymm3;
- case gdb_fpu_ymm4 : return fpu_ymm4;
- case gdb_fpu_ymm5 : return fpu_ymm5;
- case gdb_fpu_ymm6 : return fpu_ymm6;
- case gdb_fpu_ymm7 : return fpu_ymm7;
- case gdb_fpu_ymm8 : return fpu_ymm8;
- case gdb_fpu_ymm9 : return fpu_ymm9;
- case gdb_fpu_ymm10 : return fpu_ymm10;
- case gdb_fpu_ymm11 : return fpu_ymm11;
- case gdb_fpu_ymm12 : return fpu_ymm12;
- case gdb_fpu_ymm13 : return fpu_ymm13;
- case gdb_fpu_ymm14 : return fpu_ymm14;
- case gdb_fpu_ymm15 : return fpu_ymm15;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
- else if (kind == eRegisterKindLLDB)
- {
- return num;
- }
- }
- }
- }
-
- return LLDB_INVALID_REGNUM;
-}
-
-uint32_t
-RegisterContext_x86_64::NumSupportedHardwareWatchpoints()
-{
- // Available debug address registers: dr0, dr1, dr2, dr3
- return 4;
-}
-
-bool
-RegisterContext_x86_64::IsWatchpointVacant(uint32_t hw_index)
-{
- bool is_vacant = false;
- RegisterValue value;
-
- assert(hw_index < NumSupportedHardwareWatchpoints());
-
- if (m_watchpoints_initialized == false)
- {
- // Reset the debug status and debug control registers
- RegisterValue zero_bits = RegisterValue(uint64_t(0));
- if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits))
- assert(false && "Could not initialize watchpoint registers");
- m_watchpoints_initialized = true;
- }
-
- if (ReadRegister(dr7, value))
- {
- uint64_t val = value.GetAsUInt64();
- is_vacant = (val & (3 << 2*hw_index)) == 0;
- }
-
- return is_vacant;
-}
-
-static uint32_t
-size_and_rw_bits(size_t size, bool read, bool write)
-{
- uint32_t rw;
- if (read) {
- rw = 0x3; // READ or READ/WRITE
- } else if (write) {
- rw = 0x1; // WRITE
- } else {
- assert(0 && "read and write cannot both be false");
- }
-
- switch (size) {
- case 1:
- return rw;
- case 2:
- return (0x1 << 2) | rw;
- case 4:
- return (0x3 << 2) | rw;
- case 8:
- return (0x2 << 2) | rw;
- default:
- assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
- }
-}
-
-uint32_t
-RegisterContext_x86_64::SetHardwareWatchpoint(addr_t addr, size_t size,
- bool read, bool write)
-{
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- uint32_t hw_index;
-
- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
- {
- if (IsWatchpointVacant(hw_index))
- return SetHardwareWatchpointWithIndex(addr, size,
- read, write,
- hw_index);
- }
-
- return LLDB_INVALID_INDEX32;
-}
-
-bool
-RegisterContext_x86_64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
- bool read, bool write,
- uint32_t hw_index)
-{
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
-
- if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints)
- return false;
-
- if (!(size == 1 || size == 2 || size == 4 || size == 8))
- return false;
-
- if (read == false && write == false)
- return false;
-
- if (!IsWatchpointVacant(hw_index))
- return false;
-
- // Set both dr7 (debug control register) and dri (debug address register).
-
- // dr7{7-0} encodes the local/gloabl enable bits:
- // global enable --. .-- local enable
- // | |
- // v v
- // dr0 -> bits{1-0}
- // dr1 -> bits{3-2}
- // dr2 -> bits{5-4}
- // dr3 -> bits{7-6}
- //
- // dr7{31-16} encodes the rw/len bits:
- // b_x+3, b_x+2, b_x+1, b_x
- // where bits{x+1, x} => rw
- // 0b00: execute, 0b01: write, 0b11: read-or-write,
- // 0b10: io read-or-write (unused)
- // and bits{x+3, x+2} => len
- // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
- //
- // dr0 -> bits{19-16}
- // dr1 -> bits{23-20}
- // dr2 -> bits{27-24}
- // dr3 -> bits{31-28}
- if (hw_index < num_hw_watchpoints)
- {
- RegisterValue current_dr7_bits;
-
- if (ReadRegister(dr7, current_dr7_bits))
- {
- uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() |
- (1 << (2*hw_index) |
- size_and_rw_bits(size, read, write) <<
- (16+4*hw_index));
-
- if (WriteRegister(dr0 + hw_index, RegisterValue(addr)) &&
- WriteRegister(dr7, RegisterValue(new_dr7_bits)))
- return true;
- }
- }
-
- return false;
-}
-
-bool
-RegisterContext_x86_64::ClearHardwareWatchpoint(uint32_t hw_index)
-{
- if (hw_index < NumSupportedHardwareWatchpoints())
- {
- RegisterValue current_dr7_bits;
-
- if (ReadRegister(dr7, current_dr7_bits))
- {
- uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() & ~(3 << (2*hw_index));
-
- if (WriteRegister(dr7, RegisterValue(new_dr7_bits)))
- return true;
- }
- }
-
- return false;
-}
-
-bool
-RegisterContext_x86_64::IsWatchpointHit(uint32_t hw_index)
-{
- bool is_hit = false;
-
- if (m_watchpoints_initialized == false)
- {
- // Reset the debug status and debug control registers
- RegisterValue zero_bits = RegisterValue(uint64_t(0));
- if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits))
- assert(false && "Could not initialize watchpoint registers");
- m_watchpoints_initialized = true;
- }
-
- if (hw_index < NumSupportedHardwareWatchpoints())
- {
- RegisterValue value;
-
- if (ReadRegister(dr6, value))
- {
- uint64_t val = value.GetAsUInt64();
- is_hit = val & (1 << hw_index);
- }
- }
-
- return is_hit;
-}
-
-addr_t
-RegisterContext_x86_64::GetWatchpointAddress(uint32_t hw_index)
-{
- addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS;
-
- if (hw_index < NumSupportedHardwareWatchpoints())
- {
- if (!IsWatchpointVacant(hw_index))
- {
- RegisterValue value;
-
- if (ReadRegister(dr0 + hw_index, value))
- wp_monitor_addr = value.GetAsUInt64();
- }
- }
-
- return wp_monitor_addr;
-}
-
-
-bool
-RegisterContext_x86_64::ClearWatchpointHits()
-{
- return WriteRegister(dr6, RegisterValue((uint64_t)0));
-}
-
-bool
-RegisterContext_x86_64::HardwareSingleStep(bool enable)
-{
- enum { TRACE_BIT = 0x100 };
- uint64_t rflags;
-
- if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL)
- return false;
-
- if (enable)
- {
- if (rflags & TRACE_BIT)
- return true;
-
- rflags |= TRACE_BIT;
- }
- else
- {
- if (!(rflags & TRACE_BIT))
- return false;
-
- rflags &= ~TRACE_BIT;
- }
-
- return WriteRegisterFromUnsigned(gpr_rflags, rflags);
-}
-
-#if defined(__linux__) or defined(__FreeBSD__)
-
-ProcessMonitor &
-RegisterContext_x86_64::GetMonitor()
-{
- ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
- return process->GetMonitor();
-}
-
-bool
-RegisterContext_x86_64::ReadGPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(m_thread.GetID(), &m_gpr, GetGPRSize());
-}
-
-bool
-RegisterContext_x86_64::ReadFPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- if (m_fpr_type == eFXSAVE)
- return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
-
- if (m_fpr_type == eXSAVE)
- return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
- return false;
-}
-
-bool
-RegisterContext_x86_64::WriteGPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(m_thread.GetID(), &m_gpr, GetGPRSize());
-}
-
-bool
-RegisterContext_x86_64::WriteFPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- if (m_fpr_type == eFXSAVE)
- return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
-
- if (m_fpr_type == eXSAVE)
- return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
- return false;
-}
-
-bool
-RegisterContext_x86_64::ReadRegister(const unsigned reg,
- RegisterValue &value)
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(m_thread.GetID(),
- GetRegisterOffset(reg),
- GetRegisterName(reg),
- GetRegisterSize(reg),
- value);
-}
-
-bool
-RegisterContext_x86_64::WriteRegister(const unsigned reg,
- const RegisterValue &value)
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(m_thread.GetID(),
- GetRegisterOffset(reg),
- GetRegisterName(reg),
- value);
-}
-
-#else
-
-bool
-RegisterContext_x86_64::ReadGPR()
-{
- llvm_unreachable("not implemented");
- return false;
-}
-
-bool
-RegisterContext_x86_64::ReadFPR()
-{
- llvm_unreachable("not implemented");
- return false;
-}
-
-bool
-RegisterContext_x86_64::WriteGPR()
-{
- llvm_unreachable("not implemented");
- return false;
-}
-
-bool
-RegisterContext_x86_64::WriteFPR()
-{
- llvm_unreachable("not implemented");
- return false;
-}
-
-bool
-RegisterContext_x86_64::ReadRegister(const unsigned reg,
- RegisterValue &value)
-{
- llvm_unreachable("not implemented");
- return false;
-}
-
-bool
-RegisterContext_x86_64::WriteRegister(const unsigned reg,
- const RegisterValue &value)
-{
- llvm_unreachable("not implemented");
- return false;
-}
-
-#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86_64.h b/source/Plugins/Process/POSIX/RegisterContext_x86_64.h
deleted file mode 100644
index 9d59bd78e547..000000000000
--- a/source/Plugins/Process/POSIX/RegisterContext_x86_64.h
+++ /dev/null
@@ -1,347 +0,0 @@
-//===-- RegisterContext_x86_64.h ---------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContext_x86_64_H_
-#define liblldb_RegisterContext_x86_64_H_
-
-#include "lldb/Core/Log.h"
-#include "RegisterContextPOSIX.h"
-
-class ProcessMonitor;
-
-// Internal codes for all x86_64 registers.
-enum
-{
- k_first_gpr,
- gpr_rax = k_first_gpr,
- gpr_rbx,
- gpr_rcx,
- gpr_rdx,
- gpr_rdi,
- gpr_rsi,
- gpr_rbp,
- gpr_rsp,
- gpr_r8,
- gpr_r9,
- gpr_r10,
- gpr_r11,
- gpr_r12,
- gpr_r13,
- gpr_r14,
- gpr_r15,
- gpr_rip,
- gpr_rflags,
- gpr_cs,
- gpr_fs,
- gpr_gs,
- gpr_ss,
- gpr_ds,
- gpr_es,
- k_first_i386,
- gpr_eax = k_first_i386,
- gpr_ebx,
- gpr_ecx,
- gpr_edx,
- gpr_edi,
- gpr_esi,
- gpr_ebp,
- gpr_esp,
- gpr_eip,
- gpr_eflags, // eRegisterKindLLDB == 33
- k_last_i386 = gpr_eflags,
- k_last_gpr = gpr_eflags,
-
- k_first_fpr,
- fpu_fcw = k_first_fpr,
- fpu_fsw,
- fpu_ftw,
- fpu_fop,
- fpu_ip,
- fpu_cs,
- fpu_dp,
- fpu_ds,
- fpu_mxcsr,
- fpu_mxcsrmask,
- fpu_stmm0,
- fpu_stmm1,
- fpu_stmm2,
- fpu_stmm3,
- fpu_stmm4,
- fpu_stmm5,
- fpu_stmm6,
- fpu_stmm7,
- fpu_xmm0,
- fpu_xmm1,
- fpu_xmm2,
- fpu_xmm3,
- fpu_xmm4,
- fpu_xmm5,
- fpu_xmm6,
- fpu_xmm7,
- fpu_xmm8,
- fpu_xmm9,
- fpu_xmm10,
- fpu_xmm11,
- fpu_xmm12,
- fpu_xmm13,
- fpu_xmm14,
- fpu_xmm15,
- k_last_fpr = fpu_xmm15,
- k_first_avx,
- fpu_ymm0 = k_first_avx,
- fpu_ymm1,
- fpu_ymm2,
- fpu_ymm3,
- fpu_ymm4,
- fpu_ymm5,
- fpu_ymm6,
- fpu_ymm7,
- fpu_ymm8,
- fpu_ymm9,
- fpu_ymm10,
- fpu_ymm11,
- fpu_ymm12,
- fpu_ymm13,
- fpu_ymm14,
- fpu_ymm15,
- k_last_avx = fpu_ymm15,
-
- dr0,
- dr1,
- dr2,
- dr3,
- dr4,
- dr5,
- dr6,
- dr7,
-
- k_num_registers,
- k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
- k_num_fpr_registers = k_last_fpr - k_first_fpr + 1,
- k_num_avx_registers = k_last_avx - k_first_avx + 1
-};
-
-class RegisterContext_x86_64
- : public RegisterContextPOSIX
-{
-public:
- RegisterContext_x86_64 (lldb_private::Thread &thread,
- uint32_t concrete_frame_idx);
-
- ~RegisterContext_x86_64();
-
- void
- Invalidate();
-
- void
- InvalidateAllRegisters();
-
- size_t
- GetRegisterCount();
-
- virtual size_t
- GetGPRSize() = 0;
-
- 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);
-
- unsigned
- GetRegisterIndexFromOffset(unsigned offset);
-
- const char *
- GetRegisterName(unsigned reg);
-
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value);
-
- bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
-
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value);
-
- bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
-
- uint32_t
- ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
-
- uint32_t
- NumSupportedHardwareWatchpoints();
-
- uint32_t
- SetHardwareWatchpoint(lldb::addr_t, size_t size, bool read, bool write);
-
- bool
- SetHardwareWatchpointWithIndex(lldb::addr_t, size_t size, bool read,
- bool write, uint32_t hw_index);
-
- bool
- ClearHardwareWatchpoint(uint32_t hw_index);
-
- bool
- HardwareSingleStep(bool enable);
-
- bool
- UpdateAfterBreakpoint();
-
- bool
- IsWatchpointVacant(uint32_t hw_index);
-
- bool
- IsWatchpointHit (uint32_t hw_index);
-
- lldb::addr_t
- GetWatchpointAddress (uint32_t hw_index);
-
- bool
- ClearWatchpointHits();
-
- //---------------------------------------------------------------------------
- // Generic floating-point registers
- //---------------------------------------------------------------------------
-
- struct MMSReg
- {
- uint8_t bytes[10];
- uint8_t pad[6];
- };
-
- struct XMMReg
- {
- uint8_t bytes[16]; // 128-bits for each XMM register
- };
-
- struct FXSAVE
- {
- uint16_t fcw;
- uint16_t fsw;
- uint16_t ftw;
- uint16_t fop;
- uint64_t ip;
- uint64_t dp;
- uint32_t mxcsr;
- uint32_t mxcsrmask;
- MMSReg stmm[8];
- XMMReg xmm[16];
- uint32_t padding[24];
- };
-
- //---------------------------------------------------------------------------
- // Extended floating-point registers
- //---------------------------------------------------------------------------
- struct YMMHReg
- {
- uint8_t bytes[16]; // 16 * 8 bits for the high bytes of each YMM register
- };
-
- struct YMMReg
- {
- uint8_t bytes[32]; // 16 * 16 bits for each YMM register
- };
-
- struct YMM
- {
- YMMReg ymm[16]; // assembled from ymmh and xmm registers
- };
-
- struct XSAVE_HDR
- {
- uint64_t xstate_bv; // OS enabled xstate mask to determine the extended states supported by the processor
- uint64_t reserved1[2];
- uint64_t reserved2[5];
- } __attribute__((packed));
-
- // x86 extensions to FXSAVE (i.e. for AVX processors)
- struct XSAVE
- {
- FXSAVE i387; // floating point registers typical in i387_fxsave_struct
- XSAVE_HDR header; // The xsave_hdr_struct can be used to determine if the following extensions are usable
- YMMHReg ymmh[16]; // High 16 bytes of each of 16 YMM registers (the low bytes are in FXSAVE.xmm for compatibility with SSE)
- // Slot any extensions to the register file here
- } __attribute__((packed, aligned (64)));
-
- struct IOVEC
- {
- void *iov_base; // pointer to XSAVE
- size_t iov_len; // sizeof(XSAVE)
- };
-
- //---------------------------------------------------------------------------
- // Note: prefer kernel definitions over user-land
- //---------------------------------------------------------------------------
- enum FPRType
- {
- eNotValid = 0,
- eFSAVE, // TODO
- eFXSAVE,
- eSOFT, // TODO
- eXSAVE
- };
-
- // Floating-point registers
- struct FPR
- {
- // Thread state for the floating-point unit of the processor read by ptrace.
- union XSTATE {
- FXSAVE fxsave; // Generic floating-point registers.
- XSAVE xsave; // x86 extended processor state.
- } xstate;
- };
-
-protected:
- // 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();
-
- virtual bool
- ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
-
- virtual bool
- WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value);
-
-private:
- uint64_t m_gpr[k_num_gpr_registers]; // general purpose registers.
- FPRType m_fpr_type; // determines the type of data stored by union FPR, if any.
- FPR m_fpr; // floating-point registers including extended register sets.
- IOVEC m_iovec; // wrapper for xsave.
- YMM m_ymm_set; // copy of ymmh and xmm register halves.
-
- ProcessMonitor &GetMonitor();
- lldb::ByteOrder GetByteOrder();
-
- bool CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order);
- bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);
- bool IsFPR(unsigned reg, FPRType fpr_type);
-
- bool ReadGPR();
- bool ReadFPR();
-
- bool WriteGPR();
- bool WriteFPR();
-};
-
-#endif // #ifndef liblldb_RegisterContext_x86_64_H_
diff --git a/source/Plugins/Process/POSIX/RegisterInfos_i386.h b/source/Plugins/Process/POSIX/RegisterInfos_i386.h
new file mode 100644
index 000000000000..7c516568cd62
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterInfos_i386.h
@@ -0,0 +1,207 @@
+//===-- RegisterInfos_i386.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "llvm/Support/Compiler.h"
+
+#ifdef DECLARE_REGISTER_INFOS_I386_STRUCT
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname) \
+ (LLVM_EXTENSION offsetof(GPR, regname))
+
+// Computes the offset of the given FPR in the extended data area.
+#define FPR_OFFSET(regname) \
+ (LLVM_EXTENSION offsetof(FPR, xstate) + \
+ LLVM_EXTENSION offsetof(FXSAVE, regname))
+
+// Computes the offset of the YMM register assembled from register halves.
+#define YMM_OFFSET(regname) \
+ (LLVM_EXTENSION offsetof(YMM, regname))
+
+// Number of bytes needed to represent a FPR.
+#define FPR_SIZE(reg) sizeof(((FXSAVE*)NULL)->reg)
+
+// Number of bytes needed to represent the i'th FP register.
+#define FP_SIZE sizeof(((MMSReg*)NULL)->bytes)
+
+// Number of bytes needed to represent an XMM register.
+#define XMM_SIZE sizeof(XMMReg)
+
+// Number of bytes needed to represent a YMM register.
+#define YMM_SIZE sizeof(YMMReg)
+
+// 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, \
+ eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_i386 }, NULL, NULL }
+
+#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \
+ { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4, fpu_##name##_i386 }, NULL, NULL }
+
+// RegisterKind: GCC, DWARF, Generic, GDB, LLDB
+
+#define DEFINE_FP_ST(reg, i) \
+ { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
+ eEncodingVector, eFormatVectorOfUInt8, \
+ { gcc_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, gdb_st##i##_i386, fpu_st##i##_i386 }, \
+ NULL, NULL }
+
+#define DEFINE_FP_MM(reg, i) \
+ { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
+ eEncodingUint, eFormatHex, \
+ { gcc_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, gdb_mm##i##_i386, fpu_mm##i##_i386 }, \
+ NULL, NULL }
+
+#define DEFINE_XMM(reg, i) \
+ { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
+ eEncodingVector, eFormatVectorOfUInt8, \
+ { gcc_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##_i386, fpu_##reg##i##_i386}, \
+ NULL, NULL }
+
+// I believe the YMM registers use dwarf_xmm_%_i386 register numbers and then differentiate based on register size.
+#define DEFINE_YMM(reg, i) \
+ { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(reg[i]), \
+ eEncodingVector, eFormatVectorOfUInt8, \
+ { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##h_i386, fpu_##reg##i##_i386 }, \
+ NULL, NULL }
+
+#define DEFINE_DR(reg, i) \
+ { #reg#i, NULL, DR_SIZE, DR_OFFSET(i), eEncodingUint, eFormatHex, \
+ { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
+
+#define DEFINE_GPR_PSEUDO_16(reg16, reg32) \
+ { #reg16, NULL, 2, GPR_OFFSET(reg32), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg16##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 }
+#define DEFINE_GPR_PSEUDO_8H(reg8, reg32) \
+ { #reg8, NULL, 1, GPR_OFFSET(reg32)+1, eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 }
+#define DEFINE_GPR_PSEUDO_8L(reg8, reg32) \
+ { #reg8, NULL, 1, GPR_OFFSET(reg32), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 }
+
+static RegisterInfo
+g_register_infos_i386[] =
+{
+ // General purpose registers.
+ DEFINE_GPR(eax, NULL, gcc_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, gdb_eax_i386),
+ DEFINE_GPR(ebx, NULL, gcc_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, gdb_ebx_i386),
+ DEFINE_GPR(ecx, NULL, gcc_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, gdb_ecx_i386),
+ DEFINE_GPR(edx, NULL, gcc_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, gdb_edx_i386),
+ DEFINE_GPR(edi, NULL, gcc_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, gdb_edi_i386),
+ DEFINE_GPR(esi, NULL, gcc_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, gdb_esi_i386),
+ DEFINE_GPR(ebp, "fp", gcc_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, gdb_ebp_i386),
+ DEFINE_GPR(esp, "sp", gcc_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, gdb_esp_i386),
+ DEFINE_GPR(eip, "pc", gcc_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, gdb_eip_i386),
+ DEFINE_GPR(eflags, "flags", gcc_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, gdb_eflags_i386),
+ DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, dwarf_cs_i386, LLDB_INVALID_REGNUM, gdb_cs_i386),
+ DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, dwarf_fs_i386, LLDB_INVALID_REGNUM, gdb_fs_i386),
+ DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, dwarf_gs_i386, LLDB_INVALID_REGNUM, gdb_gs_i386),
+ DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, dwarf_ss_i386, LLDB_INVALID_REGNUM, gdb_ss_i386),
+ DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, dwarf_ds_i386, LLDB_INVALID_REGNUM, gdb_ds_i386),
+ DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, dwarf_es_i386, LLDB_INVALID_REGNUM, gdb_es_i386),
+
+ DEFINE_GPR_PSEUDO_16(ax, eax),
+ DEFINE_GPR_PSEUDO_16(bx, ebx),
+ DEFINE_GPR_PSEUDO_16(cx, ecx),
+ DEFINE_GPR_PSEUDO_16(dx, edx),
+ DEFINE_GPR_PSEUDO_16(di, edi),
+ DEFINE_GPR_PSEUDO_16(si, esi),
+ DEFINE_GPR_PSEUDO_16(bp, ebp),
+ DEFINE_GPR_PSEUDO_16(sp, esp),
+ DEFINE_GPR_PSEUDO_8H(ah, eax),
+ DEFINE_GPR_PSEUDO_8H(bh, ebx),
+ DEFINE_GPR_PSEUDO_8H(ch, ecx),
+ DEFINE_GPR_PSEUDO_8H(dh, edx),
+ DEFINE_GPR_PSEUDO_8L(al, eax),
+ DEFINE_GPR_PSEUDO_8L(bl, ebx),
+ DEFINE_GPR_PSEUDO_8L(cl, ecx),
+ DEFINE_GPR_PSEUDO_8L(dl, edx),
+
+ // i387 Floating point registers.
+ DEFINE_FPR(fctrl, fctrl, LLDB_INVALID_REGNUM, dwarf_fctrl_i386, LLDB_INVALID_REGNUM, gdb_fctrl_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(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),
+
+ // FP registers.
+ DEFINE_FP_ST(st, 0),
+ DEFINE_FP_ST(st, 1),
+ DEFINE_FP_ST(st, 2),
+ DEFINE_FP_ST(st, 3),
+ DEFINE_FP_ST(st, 4),
+ DEFINE_FP_ST(st, 5),
+ DEFINE_FP_ST(st, 6),
+ DEFINE_FP_ST(st, 7),
+ DEFINE_FP_MM(mm, 0),
+ DEFINE_FP_MM(mm, 1),
+ DEFINE_FP_MM(mm, 2),
+ DEFINE_FP_MM(mm, 3),
+ DEFINE_FP_MM(mm, 4),
+ DEFINE_FP_MM(mm, 5),
+ DEFINE_FP_MM(mm, 6),
+ DEFINE_FP_MM(mm, 7),
+
+ // XMM registers
+ DEFINE_XMM(xmm, 0),
+ DEFINE_XMM(xmm, 1),
+ DEFINE_XMM(xmm, 2),
+ DEFINE_XMM(xmm, 3),
+ DEFINE_XMM(xmm, 4),
+ DEFINE_XMM(xmm, 5),
+ DEFINE_XMM(xmm, 6),
+ DEFINE_XMM(xmm, 7),
+
+ // Copy of YMM registers assembled from xmm and ymmh
+ DEFINE_YMM(ymm, 0),
+ DEFINE_YMM(ymm, 1),
+ DEFINE_YMM(ymm, 2),
+ DEFINE_YMM(ymm, 3),
+ DEFINE_YMM(ymm, 4),
+ DEFINE_YMM(ymm, 5),
+ DEFINE_YMM(ymm, 6),
+ DEFINE_YMM(ymm, 7),
+
+ // Debug registers for lldb internal use
+ DEFINE_DR(dr, 0),
+ DEFINE_DR(dr, 1),
+ DEFINE_DR(dr, 2),
+ DEFINE_DR(dr, 3),
+ DEFINE_DR(dr, 4),
+ DEFINE_DR(dr, 5),
+ DEFINE_DR(dr, 6),
+ DEFINE_DR(dr, 7)
+};
+static_assert((sizeof(g_register_infos_i386) / sizeof(g_register_infos_i386[0])) == k_num_registers_i386,
+ "g_register_infos_x86_64 has wrong number of register infos");
+
+#undef GPR_OFFSET
+#undef FPR_OFFSET
+#undef YMM_OFFSET
+#undef FPR_SIZE
+#undef FP_SIZE
+#undef XMM_SIZE
+#undef YMM_SIZE
+#undef DEFINE_GPR
+#undef DEFINE_FPR
+#undef DEFINE_FP
+#undef DEFINE_XMM
+#undef DEFINE_YMM
+#undef DEFINE_DR
+#undef DEFINE_GPR_PSEUDO_16
+#undef DEFINE_GPR_PSEUDO_8H
+#undef DEFINE_GPR_PSEUDO_8L
+
+#endif // DECLARE_REGISTER_INFOS_I386_STRUCT
diff --git a/source/Plugins/Process/POSIX/RegisterInfos_mips64.h b/source/Plugins/Process/POSIX/RegisterInfos_mips64.h
new file mode 100644
index 000000000000..13526e3680b7
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterInfos_mips64.h
@@ -0,0 +1,74 @@
+//===-- RegisterInfos_mips64.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname) \
+ (offsetof(GPR, regname))
+
+#ifdef DECLARE_REGISTER_INFOS_MIPS64_STRUCT
+
+// 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, \
+ eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL }
+
+static RegisterInfo
+g_register_infos_mips64[] =
+{
+ // General purpose registers. GCC, DWARF, Generic, GDB
+ DEFINE_GPR(zero, "r0", gcc_dwarf_zero_mips64, gcc_dwarf_zero_mips64, LLDB_INVALID_REGNUM, gdb_zero_mips64),
+ DEFINE_GPR(r1, NULL, gcc_dwarf_r1_mips64, gcc_dwarf_r1_mips64, LLDB_INVALID_REGNUM, gdb_r1_mips64),
+ DEFINE_GPR(r2, NULL, gcc_dwarf_r2_mips64, gcc_dwarf_r2_mips64, LLDB_INVALID_REGNUM, gdb_r2_mips64),
+ DEFINE_GPR(r3, NULL, gcc_dwarf_r3_mips64, gcc_dwarf_r3_mips64, LLDB_INVALID_REGNUM, gdb_r3_mips64),
+ DEFINE_GPR(r4, NULL, gcc_dwarf_r4_mips64, gcc_dwarf_r4_mips64, LLDB_INVALID_REGNUM, gdb_r4_mips64),
+ DEFINE_GPR(r5, NULL, gcc_dwarf_r5_mips64, gcc_dwarf_r5_mips64, LLDB_INVALID_REGNUM, gdb_r5_mips64),
+ DEFINE_GPR(r6, NULL, gcc_dwarf_r6_mips64, gcc_dwarf_r6_mips64, LLDB_INVALID_REGNUM, gdb_r6_mips64),
+ DEFINE_GPR(r7, NULL, gcc_dwarf_r7_mips64, gcc_dwarf_r7_mips64, LLDB_INVALID_REGNUM, gdb_r7_mips64),
+ DEFINE_GPR(r8, NULL, gcc_dwarf_r8_mips64, gcc_dwarf_r8_mips64, LLDB_INVALID_REGNUM, gdb_r8_mips64),
+ DEFINE_GPR(r9, NULL, gcc_dwarf_r9_mips64, gcc_dwarf_r9_mips64, LLDB_INVALID_REGNUM, gdb_r9_mips64),
+ DEFINE_GPR(r10, NULL, gcc_dwarf_r10_mips64, gcc_dwarf_r10_mips64, LLDB_INVALID_REGNUM, gdb_r10_mips64),
+ DEFINE_GPR(r11, NULL, gcc_dwarf_r11_mips64, gcc_dwarf_r11_mips64, LLDB_INVALID_REGNUM, gdb_r11_mips64),
+ DEFINE_GPR(r12, NULL, gcc_dwarf_r12_mips64, gcc_dwarf_r12_mips64, LLDB_INVALID_REGNUM, gdb_r12_mips64),
+ DEFINE_GPR(r13, NULL, gcc_dwarf_r13_mips64, gcc_dwarf_r13_mips64, LLDB_INVALID_REGNUM, gdb_r13_mips64),
+ DEFINE_GPR(r14, NULL, gcc_dwarf_r14_mips64, gcc_dwarf_r14_mips64, LLDB_INVALID_REGNUM, gdb_r14_mips64),
+ DEFINE_GPR(r15, NULL, gcc_dwarf_r15_mips64, gcc_dwarf_r15_mips64, LLDB_INVALID_REGNUM, gdb_r15_mips64),
+ DEFINE_GPR(r16, NULL, gcc_dwarf_r16_mips64, gcc_dwarf_r16_mips64, LLDB_INVALID_REGNUM, gdb_r16_mips64),
+ DEFINE_GPR(r17, NULL, gcc_dwarf_r17_mips64, gcc_dwarf_r17_mips64, LLDB_INVALID_REGNUM, gdb_r17_mips64),
+ DEFINE_GPR(r18, NULL, gcc_dwarf_r18_mips64, gcc_dwarf_r18_mips64, LLDB_INVALID_REGNUM, gdb_r18_mips64),
+ DEFINE_GPR(r19, NULL, gcc_dwarf_r19_mips64, gcc_dwarf_r19_mips64, LLDB_INVALID_REGNUM, gdb_r19_mips64),
+ DEFINE_GPR(r20, NULL, gcc_dwarf_r20_mips64, gcc_dwarf_r20_mips64, LLDB_INVALID_REGNUM, gdb_r20_mips64),
+ DEFINE_GPR(r21, NULL, gcc_dwarf_r21_mips64, gcc_dwarf_r21_mips64, LLDB_INVALID_REGNUM, gdb_r21_mips64),
+ DEFINE_GPR(r22, NULL, gcc_dwarf_r22_mips64, gcc_dwarf_r22_mips64, LLDB_INVALID_REGNUM, gdb_r22_mips64),
+ DEFINE_GPR(r23, NULL, gcc_dwarf_r23_mips64, gcc_dwarf_r23_mips64, LLDB_INVALID_REGNUM, gdb_r23_mips64),
+ DEFINE_GPR(r24, NULL, gcc_dwarf_r24_mips64, gcc_dwarf_r24_mips64, LLDB_INVALID_REGNUM, gdb_r24_mips64),
+ DEFINE_GPR(r25, NULL, gcc_dwarf_r25_mips64, gcc_dwarf_r25_mips64, LLDB_INVALID_REGNUM, gdb_r25_mips64),
+ DEFINE_GPR(r26, NULL, gcc_dwarf_r26_mips64, gcc_dwarf_r26_mips64, LLDB_INVALID_REGNUM, gdb_r26_mips64),
+ DEFINE_GPR(r27, NULL, gcc_dwarf_r27_mips64, gcc_dwarf_r27_mips64, LLDB_INVALID_REGNUM, gdb_r27_mips64),
+ DEFINE_GPR(gp, "r28", gcc_dwarf_gp_mips64, gcc_dwarf_gp_mips64, LLDB_INVALID_REGNUM, gdb_gp_mips64),
+ DEFINE_GPR(sp, "r29", gcc_dwarf_sp_mips64, gcc_dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, gdb_sp_mips64),
+ DEFINE_GPR(r30, NULL, gcc_dwarf_r30_mips64, gcc_dwarf_r30_mips64, LLDB_INVALID_REGNUM, gdb_r30_mips64),
+ DEFINE_GPR(ra, "r31", gcc_dwarf_ra_mips64, gcc_dwarf_ra_mips64, LLDB_INVALID_REGNUM, gdb_ra_mips64),
+ DEFINE_GPR(sr, NULL, gcc_dwarf_sr_mips64, gcc_dwarf_sr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(mullo, NULL, gcc_dwarf_lo_mips64, gcc_dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(mulhi, NULL, gcc_dwarf_hi_mips64, gcc_dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(badvaddr, NULL, gcc_dwarf_bad_mips64, gcc_dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(cause, NULL, gcc_dwarf_cause_mips64, gcc_dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", gcc_dwarf_pc_mips64, gcc_dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ic, NULL, gcc_dwarf_ic_mips64, gcc_dwarf_ic_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(dummy, NULL, gcc_dwarf_dummy_mips64, gcc_dwarf_dummy_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+};
+static_assert((sizeof(g_register_infos_mips64) / sizeof(g_register_infos_mips64[0])) == k_num_registers_mips64,
+ "g_register_infos_mips64 has wrong number of register infos");
+
+#undef DEFINE_GPR
+
+#endif // DECLARE_REGISTER_INFOS_MIPS64_STRUCT
+
+#undef GPR_OFFSET
+
diff --git a/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h b/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h
new file mode 100644
index 000000000000..1bab88cd5727
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h
@@ -0,0 +1,409 @@
+//===-- RegisterInfos_x86_64.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "llvm/Support/Compiler.h"
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname) \
+ (LLVM_EXTENSION offsetof(GPR, regname))
+
+// Computes the offset of the given FPR in the extended data area.
+#define FPR_OFFSET(regname) \
+ (LLVM_EXTENSION offsetof(FPR, xstate) + \
+ LLVM_EXTENSION offsetof(FXSAVE, regname))
+
+// Computes the offset of the YMM register assembled from register halves.
+#define YMM_OFFSET(regname) \
+ (LLVM_EXTENSION offsetof(YMM, regname))
+
+#ifdef DECLARE_REGISTER_INFOS_X86_64_STRUCT
+
+// Number of bytes needed to represent a FPR.
+#define FPR_SIZE(reg) sizeof(((FXSAVE*)NULL)->reg)
+
+// Number of bytes needed to represent the i'th FP register.
+#define FP_SIZE sizeof(((MMSReg*)NULL)->bytes)
+
+// Number of bytes needed to represent an XMM register.
+#define XMM_SIZE sizeof(XMMReg)
+
+// Number of bytes needed to represent a YMM register.
+#define YMM_SIZE sizeof(YMMReg)
+
+// RegisterKind: GCC, DWARF, Generic, GDB, LLDB
+
+// 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, \
+ eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_x86_64 }, NULL, NULL }
+
+#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \
+ { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4, fpu_##name##_x86_64 }, NULL, NULL }
+
+#define DEFINE_FP_ST(reg, i) \
+ { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
+ eEncodingVector, eFormatVectorOfUInt8, \
+ { gcc_dwarf_st##i##_x86_64, gcc_dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, fpu_st##i##_x86_64 }, \
+ NULL, NULL }
+
+#define DEFINE_FP_MM(reg, i) \
+ { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
+ eEncodingUint, eFormatHex, \
+ { gcc_dwarf_mm##i##_x86_64, gcc_dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, fpu_mm##i##_x86_64 }, \
+ NULL, NULL }
+
+#define DEFINE_XMM(reg, i) \
+ { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
+ eEncodingVector, eFormatVectorOfUInt8, \
+ { gcc_dwarf_##reg##i##_x86_64, gcc_dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##_x86_64, fpu_##reg##i##_x86_64}, \
+ NULL, NULL }
+
+#define DEFINE_YMM(reg, i) \
+ { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(reg[i]), \
+ eEncodingVector, eFormatVectorOfUInt8, \
+ { gcc_dwarf_##reg##i##h_x86_64, gcc_dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##h_x86_64, fpu_##reg##i##_x86_64 }, \
+ NULL, NULL }
+
+#define DEFINE_DR(reg, i) \
+ { #reg#i, NULL, DR_SIZE, DR_OFFSET(i), eEncodingUint, eFormatHex, \
+ { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
+
+#define DEFINE_GPR_PSEUDO_32(reg32, reg64) \
+ { #reg32, NULL, 4, GPR_OFFSET(reg64), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg32##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 }
+#define DEFINE_GPR_PSEUDO_16(reg16, reg64) \
+ { #reg16, NULL, 2, GPR_OFFSET(reg64), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg16##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 }
+#define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \
+ { #reg8, NULL, 1, GPR_OFFSET(reg64)+1, eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 }
+#define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \
+ { #reg8, NULL, 1, GPR_OFFSET(reg64), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 }
+
+static RegisterInfo
+g_register_infos_x86_64[] =
+{
+ // General purpose registers. GCC, DWARF, Generic, GDB
+ DEFINE_GPR(rax, NULL, gcc_dwarf_rax_x86_64, gcc_dwarf_rax_x86_64, LLDB_INVALID_REGNUM, gdb_rax_x86_64),
+ DEFINE_GPR(rbx, NULL, gcc_dwarf_rbx_x86_64, gcc_dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, gdb_rbx_x86_64),
+ DEFINE_GPR(rcx, "arg4", gcc_dwarf_rcx_x86_64, gcc_dwarf_rcx_x86_64, LLDB_INVALID_REGNUM, gdb_rcx_x86_64),
+ DEFINE_GPR(rdx, "arg3", gcc_dwarf_rdx_x86_64, gcc_dwarf_rdx_x86_64, LLDB_INVALID_REGNUM, gdb_rdx_x86_64),
+ DEFINE_GPR(rdi, "arg1", gcc_dwarf_rdi_x86_64, gcc_dwarf_rdi_x86_64, LLDB_INVALID_REGNUM, gdb_rdi_x86_64),
+ DEFINE_GPR(rsi, "arg2", gcc_dwarf_rsi_x86_64, gcc_dwarf_rsi_x86_64, LLDB_INVALID_REGNUM, gdb_rsi_x86_64),
+ DEFINE_GPR(rbp, "fp", gcc_dwarf_rbp_x86_64, gcc_dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, gdb_rbp_x86_64),
+ DEFINE_GPR(rsp, "sp", gcc_dwarf_rsp_x86_64, gcc_dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, gdb_rsp_x86_64),
+ DEFINE_GPR(r8, "arg5", gcc_dwarf_r8_x86_64, gcc_dwarf_r8_x86_64, LLDB_INVALID_REGNUM, gdb_r8_x86_64),
+ DEFINE_GPR(r9, "arg6", gcc_dwarf_r9_x86_64, gcc_dwarf_r9_x86_64, LLDB_INVALID_REGNUM, gdb_r9_x86_64),
+ DEFINE_GPR(r10, NULL, gcc_dwarf_r10_x86_64, gcc_dwarf_r10_x86_64, LLDB_INVALID_REGNUM, gdb_r10_x86_64),
+ DEFINE_GPR(r11, NULL, gcc_dwarf_r11_x86_64, gcc_dwarf_r11_x86_64, LLDB_INVALID_REGNUM, gdb_r11_x86_64),
+ DEFINE_GPR(r12, NULL, gcc_dwarf_r12_x86_64, gcc_dwarf_r12_x86_64, LLDB_INVALID_REGNUM, gdb_r12_x86_64),
+ DEFINE_GPR(r13, NULL, gcc_dwarf_r13_x86_64, gcc_dwarf_r13_x86_64, LLDB_INVALID_REGNUM, gdb_r13_x86_64),
+ DEFINE_GPR(r14, NULL, gcc_dwarf_r14_x86_64, gcc_dwarf_r14_x86_64, LLDB_INVALID_REGNUM, gdb_r14_x86_64),
+ DEFINE_GPR(r15, NULL, gcc_dwarf_r15_x86_64, gcc_dwarf_r15_x86_64, LLDB_INVALID_REGNUM, gdb_r15_x86_64),
+ DEFINE_GPR(rip, "pc", gcc_dwarf_rip_x86_64, gcc_dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, gdb_rip_x86_64),
+ DEFINE_GPR(rflags, "flags", gcc_dwarf_rflags_x86_64, gcc_dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, gdb_rflags_x86_64),
+ DEFINE_GPR(cs, NULL, gcc_dwarf_cs_x86_64, gcc_dwarf_cs_x86_64, LLDB_INVALID_REGNUM, gdb_cs_x86_64),
+ DEFINE_GPR(fs, NULL, gcc_dwarf_fs_x86_64, gcc_dwarf_fs_x86_64, LLDB_INVALID_REGNUM, gdb_fs_x86_64),
+ DEFINE_GPR(gs, NULL, gcc_dwarf_gs_x86_64, gcc_dwarf_gs_x86_64, LLDB_INVALID_REGNUM, gdb_gs_x86_64),
+ DEFINE_GPR(ss, NULL, gcc_dwarf_ss_x86_64, gcc_dwarf_ss_x86_64, LLDB_INVALID_REGNUM, gdb_ss_x86_64),
+ DEFINE_GPR(ds, NULL, gcc_dwarf_ds_x86_64, gcc_dwarf_ds_x86_64, LLDB_INVALID_REGNUM, gdb_ds_x86_64),
+ DEFINE_GPR(es, NULL, gcc_dwarf_es_x86_64, gcc_dwarf_es_x86_64, LLDB_INVALID_REGNUM, gdb_es_x86_64),
+
+ DEFINE_GPR_PSEUDO_32(eax, rax),
+ DEFINE_GPR_PSEUDO_32(ebx, rbx),
+ DEFINE_GPR_PSEUDO_32(ecx, rcx),
+ DEFINE_GPR_PSEUDO_32(edx, rdx),
+ DEFINE_GPR_PSEUDO_32(edi, rdi),
+ DEFINE_GPR_PSEUDO_32(esi, rsi),
+ DEFINE_GPR_PSEUDO_32(ebp, rbp),
+ DEFINE_GPR_PSEUDO_32(esp, rsp),
+ DEFINE_GPR_PSEUDO_32(r8d, r8),
+ DEFINE_GPR_PSEUDO_32(r9d, r9),
+ DEFINE_GPR_PSEUDO_32(r10d, r10),
+ DEFINE_GPR_PSEUDO_32(r11d, r11),
+ DEFINE_GPR_PSEUDO_32(r12d, r12),
+ DEFINE_GPR_PSEUDO_32(r13d, r13),
+ DEFINE_GPR_PSEUDO_32(r14d, r14),
+ DEFINE_GPR_PSEUDO_32(r15d, r15),
+ DEFINE_GPR_PSEUDO_16(ax, rax),
+ DEFINE_GPR_PSEUDO_16(bx, rbx),
+ DEFINE_GPR_PSEUDO_16(cx, rcx),
+ DEFINE_GPR_PSEUDO_16(dx, rdx),
+ DEFINE_GPR_PSEUDO_16(di, rdi),
+ DEFINE_GPR_PSEUDO_16(si, rsi),
+ DEFINE_GPR_PSEUDO_16(bp, rbp),
+ DEFINE_GPR_PSEUDO_16(sp, rsp),
+ DEFINE_GPR_PSEUDO_16(r8w, r8),
+ DEFINE_GPR_PSEUDO_16(r9w, r9),
+ DEFINE_GPR_PSEUDO_16(r10w, r10),
+ DEFINE_GPR_PSEUDO_16(r11w, r11),
+ DEFINE_GPR_PSEUDO_16(r12w, r12),
+ DEFINE_GPR_PSEUDO_16(r13w, r13),
+ DEFINE_GPR_PSEUDO_16(r14w, r14),
+ DEFINE_GPR_PSEUDO_16(r15w, r15),
+ DEFINE_GPR_PSEUDO_8H(ah, rax),
+ DEFINE_GPR_PSEUDO_8H(bh, rbx),
+ DEFINE_GPR_PSEUDO_8H(ch, rcx),
+ DEFINE_GPR_PSEUDO_8H(dh, rdx),
+ DEFINE_GPR_PSEUDO_8L(al, rax),
+ DEFINE_GPR_PSEUDO_8L(bl, rbx),
+ DEFINE_GPR_PSEUDO_8L(cl, rcx),
+ DEFINE_GPR_PSEUDO_8L(dl, rdx),
+ DEFINE_GPR_PSEUDO_8L(dil, rdi),
+ DEFINE_GPR_PSEUDO_8L(sil, rsi),
+ DEFINE_GPR_PSEUDO_8L(bpl, rbp),
+ DEFINE_GPR_PSEUDO_8L(spl, rsp),
+ DEFINE_GPR_PSEUDO_8L(r8l, r8),
+ DEFINE_GPR_PSEUDO_8L(r9l, r9),
+ DEFINE_GPR_PSEUDO_8L(r10l, r10),
+ DEFINE_GPR_PSEUDO_8L(r11l, r11),
+ DEFINE_GPR_PSEUDO_8L(r12l, r12),
+ DEFINE_GPR_PSEUDO_8L(r13l, r13),
+ DEFINE_GPR_PSEUDO_8L(r14l, r14),
+ DEFINE_GPR_PSEUDO_8L(r15l, r15),
+
+ // i387 Floating point registers. GCC, DWARF, Generic, GDB
+ DEFINE_FPR(fctrl, fctrl, gcc_dwarf_fctrl_x86_64, gcc_dwarf_fctrl_x86_64, LLDB_INVALID_REGNUM, gdb_fctrl_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(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),
+
+ // FP registers.
+ DEFINE_FP_ST(st, 0),
+ DEFINE_FP_ST(st, 1),
+ DEFINE_FP_ST(st, 2),
+ DEFINE_FP_ST(st, 3),
+ DEFINE_FP_ST(st, 4),
+ DEFINE_FP_ST(st, 5),
+ DEFINE_FP_ST(st, 6),
+ DEFINE_FP_ST(st, 7),
+ DEFINE_FP_MM(mm, 0),
+ DEFINE_FP_MM(mm, 1),
+ DEFINE_FP_MM(mm, 2),
+ DEFINE_FP_MM(mm, 3),
+ DEFINE_FP_MM(mm, 4),
+ DEFINE_FP_MM(mm, 5),
+ DEFINE_FP_MM(mm, 6),
+ DEFINE_FP_MM(mm, 7),
+
+ // XMM registers
+ DEFINE_XMM(xmm, 0),
+ DEFINE_XMM(xmm, 1),
+ DEFINE_XMM(xmm, 2),
+ DEFINE_XMM(xmm, 3),
+ DEFINE_XMM(xmm, 4),
+ DEFINE_XMM(xmm, 5),
+ DEFINE_XMM(xmm, 6),
+ DEFINE_XMM(xmm, 7),
+ DEFINE_XMM(xmm, 8),
+ DEFINE_XMM(xmm, 9),
+ DEFINE_XMM(xmm, 10),
+ DEFINE_XMM(xmm, 11),
+ DEFINE_XMM(xmm, 12),
+ DEFINE_XMM(xmm, 13),
+ DEFINE_XMM(xmm, 14),
+ DEFINE_XMM(xmm, 15),
+
+ // Copy of YMM registers assembled from xmm and ymmh
+ DEFINE_YMM(ymm, 0),
+ DEFINE_YMM(ymm, 1),
+ DEFINE_YMM(ymm, 2),
+ DEFINE_YMM(ymm, 3),
+ DEFINE_YMM(ymm, 4),
+ DEFINE_YMM(ymm, 5),
+ DEFINE_YMM(ymm, 6),
+ DEFINE_YMM(ymm, 7),
+ DEFINE_YMM(ymm, 8),
+ DEFINE_YMM(ymm, 9),
+ DEFINE_YMM(ymm, 10),
+ DEFINE_YMM(ymm, 11),
+ DEFINE_YMM(ymm, 12),
+ DEFINE_YMM(ymm, 13),
+ DEFINE_YMM(ymm, 14),
+ DEFINE_YMM(ymm, 15),
+
+ // Debug registers for lldb internal use
+ DEFINE_DR(dr, 0),
+ DEFINE_DR(dr, 1),
+ DEFINE_DR(dr, 2),
+ DEFINE_DR(dr, 3),
+ DEFINE_DR(dr, 4),
+ DEFINE_DR(dr, 5),
+ DEFINE_DR(dr, 6),
+ DEFINE_DR(dr, 7)
+};
+static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[0])) == k_num_registers_x86_64,
+ "g_register_infos_x86_64 has wrong number of register infos");
+
+#undef FPR_SIZE
+#undef FP_SIZE
+#undef XMM_SIZE
+#undef YMM_SIZE
+#undef DEFINE_GPR
+#undef DEFINE_FPR
+#undef DEFINE_FP
+#undef DEFINE_XMM
+#undef DEFINE_YMM
+#undef DEFINE_DR
+#undef DEFINE_GPR_PSEUDO_32
+#undef DEFINE_GPR_PSEUDO_16
+#undef DEFINE_GPR_PSEUDO_8H
+#undef DEFINE_GPR_PSEUDO_8L
+
+#endif // DECLARE_REGISTER_INFOS_X86_64_STRUCT
+
+
+#ifdef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+
+#define UPDATE_GPR_INFO(reg, reg64) \
+do { \
+ g_register_infos[gpr_##reg##_i386].byte_offset = GPR_OFFSET(reg64); \
+} while(false);
+
+#define UPDATE_GPR_INFO_8H(reg, reg64) \
+do { \
+ g_register_infos[gpr_##reg##_i386].byte_offset = GPR_OFFSET(reg64) + 1; \
+} while(false);
+
+#define UPDATE_FPR_INFO(reg, reg64) \
+do { \
+ g_register_infos[fpu_##reg##_i386].byte_offset = FPR_OFFSET(reg64); \
+} while(false);
+
+#define UPDATE_FP_INFO(reg, i) \
+do { \
+ g_register_infos[fpu_##reg##i##_i386].byte_offset = FPR_OFFSET(stmm[i]); \
+} while(false);
+
+#define UPDATE_XMM_INFO(reg, i) \
+do { \
+ g_register_infos[fpu_##reg##i##_i386].byte_offset = FPR_OFFSET(reg[i]); \
+} while(false);
+
+#define UPDATE_YMM_INFO(reg, i) \
+do { \
+ g_register_infos[fpu_##reg##i##_i386].byte_offset = YMM_OFFSET(reg[i]); \
+} while(false);
+
+#define UPDATE_DR_INFO(reg_index) \
+do { \
+ g_register_infos[dr##reg_index##_i386].byte_offset = DR_OFFSET(reg_index); \
+} while(false);
+
+ // Update the register offsets
+ UPDATE_GPR_INFO(eax, rax);
+ UPDATE_GPR_INFO(ebx, rbx);
+ UPDATE_GPR_INFO(ecx, rcx);
+ UPDATE_GPR_INFO(edx, rdx);
+ UPDATE_GPR_INFO(edi, rdi);
+ UPDATE_GPR_INFO(esi, rsi);
+ UPDATE_GPR_INFO(ebp, rbp);
+ UPDATE_GPR_INFO(esp, rsp);
+ UPDATE_GPR_INFO(eip, rip);
+ UPDATE_GPR_INFO(eflags, rflags);
+ UPDATE_GPR_INFO(cs, cs);
+ UPDATE_GPR_INFO(fs, fs);
+ UPDATE_GPR_INFO(gs, gs);
+ UPDATE_GPR_INFO(ss, ss);
+ UPDATE_GPR_INFO(ds, ds);
+ UPDATE_GPR_INFO(es, es);
+
+ UPDATE_GPR_INFO(ax, rax);
+ UPDATE_GPR_INFO(bx, rbx);
+ UPDATE_GPR_INFO(cx, rcx);
+ UPDATE_GPR_INFO(dx, rdx);
+ UPDATE_GPR_INFO(di, rdi);
+ UPDATE_GPR_INFO(si, rsi);
+ UPDATE_GPR_INFO(bp, rbp);
+ UPDATE_GPR_INFO(sp, rsp);
+ UPDATE_GPR_INFO_8H(ah, rax);
+ UPDATE_GPR_INFO_8H(bh, rbx);
+ UPDATE_GPR_INFO_8H(ch, rcx);
+ UPDATE_GPR_INFO_8H(dh, rdx);
+ UPDATE_GPR_INFO(al, rax);
+ UPDATE_GPR_INFO(bl, rbx);
+ UPDATE_GPR_INFO(cl, rcx);
+ UPDATE_GPR_INFO(dl, rdx);
+
+ UPDATE_FPR_INFO(fctrl, fctrl);
+ 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(mxcsr, mxcsr);
+ UPDATE_FPR_INFO(mxcsrmask, mxcsrmask);
+
+ UPDATE_FP_INFO(st, 0);
+ UPDATE_FP_INFO(st, 1);
+ UPDATE_FP_INFO(st, 2);
+ UPDATE_FP_INFO(st, 3);
+ UPDATE_FP_INFO(st, 4);
+ UPDATE_FP_INFO(st, 5);
+ UPDATE_FP_INFO(st, 6);
+ UPDATE_FP_INFO(st, 7);
+ UPDATE_FP_INFO(mm, 0);
+ UPDATE_FP_INFO(mm, 1);
+ UPDATE_FP_INFO(mm, 2);
+ UPDATE_FP_INFO(mm, 3);
+ UPDATE_FP_INFO(mm, 4);
+ UPDATE_FP_INFO(mm, 5);
+ UPDATE_FP_INFO(mm, 6);
+ UPDATE_FP_INFO(mm, 7);
+
+ UPDATE_XMM_INFO(xmm, 0);
+ UPDATE_XMM_INFO(xmm, 1);
+ UPDATE_XMM_INFO(xmm, 2);
+ UPDATE_XMM_INFO(xmm, 3);
+ UPDATE_XMM_INFO(xmm, 4);
+ UPDATE_XMM_INFO(xmm, 5);
+ UPDATE_XMM_INFO(xmm, 6);
+ UPDATE_XMM_INFO(xmm, 7);
+
+ UPDATE_YMM_INFO(ymm, 0);
+ UPDATE_YMM_INFO(ymm, 1);
+ UPDATE_YMM_INFO(ymm, 2);
+ UPDATE_YMM_INFO(ymm, 3);
+ UPDATE_YMM_INFO(ymm, 4);
+ UPDATE_YMM_INFO(ymm, 5);
+ UPDATE_YMM_INFO(ymm, 6);
+ UPDATE_YMM_INFO(ymm, 7);
+
+ UPDATE_DR_INFO(0);
+ UPDATE_DR_INFO(1);
+ UPDATE_DR_INFO(2);
+ UPDATE_DR_INFO(3);
+ UPDATE_DR_INFO(4);
+ UPDATE_DR_INFO(5);
+ UPDATE_DR_INFO(6);
+ UPDATE_DR_INFO(7);
+
+#undef UPDATE_GPR_INFO
+#undef UPDATE_GPR_INFO_8H
+#undef UPDATE_FPR_INFO
+#undef UPDATE_FP_INFO
+#undef UPDATE_XMM_INFO
+#undef UPDATE_YMM_INFO
+#undef UPDATE_DR_INFO
+
+#endif // UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+
+#undef GPR_OFFSET
+#undef FPR_OFFSET
+#undef YMM_OFFSET
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 0c95d66cef94..dc90b7ae02c3 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -16,6 +16,9 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/DataFormatters/FormatManager.h"
#ifndef LLDB_DISABLE_PYTHON
#include "lldb/Interpreter/PythonDataObjects.h"
@@ -29,18 +32,24 @@ DynamicRegisterInfo::DynamicRegisterInfo () :
m_sets (),
m_set_reg_nums (),
m_set_names (),
- m_reg_data_byte_size (0)
+ m_value_regs_map (),
+ m_invalidate_regs_map (),
+ m_reg_data_byte_size (0),
+ m_finalized (false)
{
}
-DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict) :
+DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict, ByteOrder byte_order) :
m_regs (),
m_sets (),
m_set_reg_nums (),
m_set_names (),
- m_reg_data_byte_size (0)
+ m_value_regs_map (),
+ m_invalidate_regs_map (),
+ m_reg_data_byte_size (0),
+ m_finalized (false)
{
- SetRegisterInfo (dict);
+ SetRegisterInfo (dict, byte_order);
}
DynamicRegisterInfo::~DynamicRegisterInfo ()
@@ -49,8 +58,10 @@ DynamicRegisterInfo::~DynamicRegisterInfo ()
size_t
-DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict)
+DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict,
+ ByteOrder byte_order)
{
+ assert(!m_finalized);
#ifndef LLDB_DISABLE_PYTHON
PythonList sets (dict.GetItemForKey("sets"));
if (sets)
@@ -89,6 +100,12 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
PythonString gcc_pystr("gcc");
PythonString dwarf_pystr("dwarf");
PythonString generic_pystr("generic");
+ PythonString slice_pystr("slice");
+ PythonString composite_pystr("composite");
+ PythonString invalidate_regs_pystr("invalidate-regs");
+
+// typedef std::map<std::string, std::vector<std::string> > InvalidateNameMap;
+// InvalidateNameMap invalidate_map;
for (uint32_t i=0; i<num_regs; ++i)
{
PythonDictionary reg_info_dict(regs.GetItemAtIndex(i));
@@ -96,6 +113,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
{
// { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
RegisterInfo reg_info;
+ std::vector<uint32_t> value_regs;
+ std::vector<uint32_t> invalidate_regs;
bzero (&reg_info, sizeof(reg_info));
reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString();
@@ -111,16 +130,177 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
if (reg_info.byte_offset == UINT32_MAX)
{
- Clear();
- return 0;
+ // No offset for this register, see if the register has a value expression
+ // which indicates this register is part of another register. Value expressions
+ // are things like "rax[31:0]" which state that the current register's value
+ // is in a concrete register "rax" in bits 31:0. If there is a value expression
+ // we can calculate the offset
+ bool success = false;
+ const char *slice_cstr = reg_info_dict.GetItemForKeyAsString(slice_pystr);
+ if (slice_cstr)
+ {
+ // Slices use the following format:
+ // REGNAME[MSBIT:LSBIT]
+ // REGNAME - name of the register to grab a slice of
+ // MSBIT - the most significant bit at which the current register value starts at
+ // LSBIT - the least significant bit at which the current register value ends at
+ static RegularExpression g_bitfield_regex("([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]");
+ RegularExpression::Match regex_match(3);
+ if (g_bitfield_regex.Execute(slice_cstr, &regex_match))
+ {
+ llvm::StringRef reg_name_str;
+ std::string msbit_str;
+ std::string lsbit_str;
+ if (regex_match.GetMatchAtIndex(slice_cstr, 1, reg_name_str) &&
+ regex_match.GetMatchAtIndex(slice_cstr, 2, msbit_str) &&
+ regex_match.GetMatchAtIndex(slice_cstr, 3, lsbit_str))
+ {
+ const uint32_t msbit = Args::StringToUInt32(msbit_str.c_str(), UINT32_MAX);
+ const uint32_t lsbit = Args::StringToUInt32(lsbit_str.c_str(), UINT32_MAX);
+ if (msbit != UINT32_MAX && lsbit != UINT32_MAX)
+ {
+ if (msbit > lsbit)
+ {
+ const uint32_t msbyte = msbit / 8;
+ const uint32_t lsbyte = lsbit / 8;
+
+ ConstString containing_reg_name(reg_name_str);
+
+ RegisterInfo *containing_reg_info = GetRegisterInfo (containing_reg_name);
+ if (containing_reg_info)
+ {
+ const uint32_t max_bit = containing_reg_info->byte_size * 8;
+ if (msbit < max_bit && lsbit < max_bit)
+ {
+ m_invalidate_regs_map[containing_reg_info->kinds[eRegisterKindLLDB]].push_back(i);
+ m_value_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]);
+ m_invalidate_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]);
+
+ if (byte_order == eByteOrderLittle)
+ {
+ success = true;
+ reg_info.byte_offset = containing_reg_info->byte_offset + lsbyte;
+ }
+ else if (byte_order == eByteOrderBig)
+ {
+ success = true;
+ reg_info.byte_offset = containing_reg_info->byte_offset + msbyte;
+ }
+ else
+ {
+ assert(!"Invalid byte order");
+ }
+ }
+ else
+ {
+ if (msbit > max_bit)
+ printf("error: msbit (%u) must be less than the bitsize of the register (%u)\n", msbit, max_bit);
+ else
+ printf("error: lsbit (%u) must be less than the bitsize of the register (%u)\n", lsbit, max_bit);
+ }
+ }
+ else
+ {
+ printf("error: invalid concrete register \"%s\"\n", containing_reg_name.GetCString());
+ }
+ }
+ else
+ {
+ printf("error: msbit (%u) must be greater than lsbit (%u)\n", msbit, lsbit);
+ }
+ }
+ else
+ {
+ printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, lsbit);
+ }
+ }
+ else
+ {
+ // TODO: print error invalid slice string that doesn't follow the format
+ printf("error: failed to extract regex matches for parsing the register bitfield regex\n");
+
+ }
+ }
+ else
+ {
+ // TODO: print error invalid slice string that doesn't follow the format
+ printf("error: failed to match against register bitfield regex\n");
+ }
+ }
+ else
+ {
+ PythonList composite_reg_list (reg_info_dict.GetItemForKey(composite_pystr));
+ if (composite_reg_list)
+ {
+ const size_t num_composite_regs = composite_reg_list.GetSize();
+ if (num_composite_regs > 0)
+ {
+ uint32_t composite_offset = UINT32_MAX;
+ for (uint32_t composite_idx=0; composite_idx<num_composite_regs; ++composite_idx)
+ {
+ PythonString composite_reg_name_pystr(composite_reg_list.GetItemAtIndex(composite_idx));
+ if (composite_reg_name_pystr)
+ {
+ ConstString composite_reg_name(composite_reg_name_pystr.GetString());
+ if (composite_reg_name)
+ {
+ RegisterInfo *composite_reg_info = GetRegisterInfo (composite_reg_name);
+ if (composite_reg_info)
+ {
+ if (composite_offset > composite_reg_info->byte_offset)
+ composite_offset = composite_reg_info->byte_offset;
+ m_value_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]);
+ m_invalidate_regs_map[composite_reg_info->kinds[eRegisterKindLLDB]].push_back(i);
+ m_invalidate_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]);
+ }
+ else
+ {
+ // TODO: print error invalid slice string that doesn't follow the format
+ printf("error: failed to find composite register by name: \"%s\"\n", composite_reg_name.GetCString());
+ }
+ }
+ else
+ {
+ printf("error: 'composite' key contained an empty string\n");
+ }
+ }
+ else
+ {
+ printf("error: 'composite' list value wasn't a python string\n");
+ }
+ }
+ if (composite_offset != UINT32_MAX)
+ {
+ reg_info.byte_offset = composite_offset;
+ success = m_value_regs_map.find(i) != m_value_regs_map.end();
+ }
+ else
+ {
+ printf("error: 'composite' registers must specify at least one real register\n");
+ }
+ }
+ else
+ {
+ printf("error: 'composite' list was empty\n");
+ }
+ }
+ }
+
+
+ if (!success)
+ {
+ Clear();
+ return 0;
+ }
}
- reg_info.byte_size = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0) / 8;
-
- if (reg_info.byte_size == 0)
+ const int64_t bitsize = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0);
+ if (bitsize == 0)
{
Clear();
return 0;
}
+
+ reg_info.byte_size = bitsize / 8;
const char *format_cstr = reg_info_dict.GetItemForKeyAsString(format_pystr);
if (format_cstr)
@@ -132,13 +312,15 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
}
}
else
- reg_info.format = eFormatHex;
-
+ {
+ reg_info.format = (Format)reg_info_dict.GetItemForKeyAsInteger (format_pystr, eFormatHex);
+ }
+
const char *encoding_cstr = reg_info_dict.GetItemForKeyAsString(encoding_pystr);
if (encoding_cstr)
reg_info.encoding = Args::StringToEncoding (encoding_cstr, eEncodingUint);
else
- reg_info.encoding = eEncodingUint;
+ 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())
@@ -147,11 +329,75 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
return 0;
}
+ // Fill in the register numbers
reg_info.kinds[lldb::eRegisterKindLLDB] = i;
reg_info.kinds[lldb::eRegisterKindGDB] = i;
reg_info.kinds[lldb::eRegisterKindGCC] = reg_info_dict.GetItemForKeyAsInteger(gcc_pystr, LLDB_INVALID_REGNUM);
reg_info.kinds[lldb::eRegisterKindDWARF] = reg_info_dict.GetItemForKeyAsInteger(dwarf_pystr, LLDB_INVALID_REGNUM);
- reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (reg_info_dict.GetItemForKeyAsString(generic_pystr));
+ const char *generic_cstr = reg_info_dict.GetItemForKeyAsString(generic_pystr);
+ if (generic_cstr)
+ reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (generic_cstr);
+ else
+ reg_info.kinds[lldb::eRegisterKindGeneric] = reg_info_dict.GetItemForKeyAsInteger(generic_pystr, LLDB_INVALID_REGNUM);
+
+ // Check if this register invalidates any other register values when it is modified
+ PythonList invalidate_reg_list (reg_info_dict.GetItemForKey(invalidate_regs_pystr));
+ if (invalidate_reg_list)
+ {
+ const size_t num_regs = invalidate_reg_list.GetSize();
+ if (num_regs > 0)
+ {
+ for (uint32_t idx=0; idx<num_regs; ++idx)
+ {
+ PythonObject invalidate_reg_object (invalidate_reg_list.GetItemAtIndex(idx));
+ PythonString invalidate_reg_name_pystr(invalidate_reg_object);
+ if (invalidate_reg_name_pystr)
+ {
+ ConstString invalidate_reg_name(invalidate_reg_name_pystr.GetString());
+ if (invalidate_reg_name)
+ {
+ RegisterInfo *invalidate_reg_info = GetRegisterInfo (invalidate_reg_name);
+ if (invalidate_reg_info)
+ {
+ m_invalidate_regs_map[i].push_back(invalidate_reg_info->kinds[eRegisterKindLLDB]);
+ }
+ else
+ {
+ // TODO: print error invalid slice string that doesn't follow the format
+ printf("error: failed to find a 'invalidate-regs' register for \"%s\" while parsing register \"%s\"\n", invalidate_reg_name.GetCString(), reg_info.name);
+ }
+ }
+ else
+ {
+ printf("error: 'invalidate-regs' list value was an empty string\n");
+ }
+ }
+ else
+ {
+ PythonInteger invalidate_reg_num(invalidate_reg_object);
+
+ if (invalidate_reg_num)
+ {
+ const int64_t r = invalidate_reg_num.GetInteger();
+ if (r != UINT64_MAX)
+ m_invalidate_regs_map[i].push_back(r);
+ else
+ printf("error: 'invalidate-regs' list value wasn't a valid integer\n");
+ }
+ else
+ {
+ printf("error: 'invalidate-regs' list value wasn't a python string or integer\n");
+ }
+ }
+ }
+ }
+ else
+ {
+ printf("error: 'invalidate-regs' contained an empty list\n");
+ }
+ }
+
+ // Calculate the register offset
const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
if (m_reg_data_byte_size < end_reg_offset)
m_reg_data_byte_size = end_reg_offset;
@@ -169,7 +415,7 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
Finalize ();
}
#endif
- return 0;
+ return m_regs.size();
}
@@ -179,10 +425,22 @@ DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info,
ConstString &reg_alt_name,
ConstString &set_name)
{
+ assert(!m_finalized);
const uint32_t reg_num = m_regs.size();
reg_info.name = reg_name.AsCString();
assert (reg_info.name);
reg_info.alt_name = reg_alt_name.AsCString(NULL);
+ uint32_t i;
+ if (reg_info.value_regs)
+ {
+ for (i=0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i)
+ m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]);
+ }
+ if (reg_info.invalidate_regs)
+ {
+ for (i=0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i)
+ m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]);
+ }
m_regs.push_back (reg_info);
uint32_t set = GetRegisterSetIndexByName (set_name, true);
assert (set < m_sets.size());
@@ -197,12 +455,99 @@ DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info,
void
DynamicRegisterInfo::Finalize ()
{
- for (uint32_t set = 0; set < m_sets.size(); ++set)
+ if (m_finalized)
+ return;
+
+ m_finalized = true;
+ const size_t num_sets = m_sets.size();
+ for (size_t set = 0; set < num_sets; ++set)
{
assert (m_sets.size() == m_set_reg_nums.size());
m_sets[set].num_registers = m_set_reg_nums[set].size();
m_sets[set].registers = &m_set_reg_nums[set][0];
}
+
+ // sort and unique all value registers and make sure each is terminated with
+ // LLDB_INVALID_REGNUM
+
+ for (reg_to_regs_map::iterator pos = m_value_regs_map.begin(), end = m_value_regs_map.end();
+ pos != end;
+ ++pos)
+ {
+ if (pos->second.size() > 1)
+ {
+ std::sort (pos->second.begin(), pos->second.end());
+ reg_num_collection::iterator unique_end = std::unique (pos->second.begin(), pos->second.end());
+ if (unique_end != pos->second.end())
+ pos->second.erase(unique_end, pos->second.end());
+ }
+ assert (!pos->second.empty());
+ if (pos->second.back() != LLDB_INVALID_REGNUM)
+ pos->second.push_back(LLDB_INVALID_REGNUM);
+ }
+
+ // Now update all value_regs with each register info as needed
+ const size_t num_regs = m_regs.size();
+ for (size_t i=0; i<num_regs; ++i)
+ {
+ if (m_value_regs_map.find(i) != m_value_regs_map.end())
+ m_regs[i].value_regs = m_value_regs_map[i].data();
+ else
+ m_regs[i].value_regs = NULL;
+ }
+
+ // Expand all invalidation dependencies
+ for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), end = m_invalidate_regs_map.end();
+ pos != end;
+ ++pos)
+ {
+ const uint32_t reg_num = pos->first;
+
+ if (m_regs[reg_num].value_regs)
+ {
+ reg_num_collection extra_invalid_regs;
+ for (const uint32_t invalidate_reg_num : pos->second)
+ {
+ reg_to_regs_map::iterator invalidate_pos = m_invalidate_regs_map.find(invalidate_reg_num);
+ if (invalidate_pos != m_invalidate_regs_map.end())
+ {
+ for (const uint32_t concrete_invalidate_reg_num : invalidate_pos->second)
+ {
+ if (concrete_invalidate_reg_num != reg_num)
+ extra_invalid_regs.push_back(concrete_invalidate_reg_num);
+ }
+ }
+ }
+ pos->second.insert(pos->second.end(), extra_invalid_regs.begin(), extra_invalid_regs.end());
+ }
+ }
+
+ // sort and unique all invalidate registers and make sure each is terminated with
+ // LLDB_INVALID_REGNUM
+ for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), end = m_invalidate_regs_map.end();
+ pos != end;
+ ++pos)
+ {
+ if (pos->second.size() > 1)
+ {
+ std::sort (pos->second.begin(), pos->second.end());
+ reg_num_collection::iterator unique_end = std::unique (pos->second.begin(), pos->second.end());
+ if (unique_end != pos->second.end())
+ pos->second.erase(unique_end, pos->second.end());
+ }
+ assert (!pos->second.empty());
+ if (pos->second.back() != LLDB_INVALID_REGNUM)
+ pos->second.push_back(LLDB_INVALID_REGNUM);
+ }
+
+ // Now update all invalidate_regs with each register info as needed
+ for (size_t i=0; i<num_regs; ++i)
+ {
+ if (m_invalidate_regs_map.find(i) != m_invalidate_regs_map.end())
+ m_regs[i].invalidate_regs = m_invalidate_regs_map[i].data();
+ else
+ m_regs[i].invalidate_regs = NULL;
+ }
}
size_t
@@ -276,4 +621,83 @@ DynamicRegisterInfo::Clear()
m_sets.clear();
m_set_reg_nums.clear();
m_set_names.clear();
+ m_value_regs_map.clear();
+ m_invalidate_regs_map.clear();
+ m_reg_data_byte_size = 0;
+ m_finalized = false;
+}
+
+void
+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);
+ for (size_t i=0; i<num_regs; ++i)
+ {
+ s.Printf("[%3zu] name = %-10s", 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,
+ m_regs[i].encoding,
+ FormatManager::GetFormatAsCString (m_regs[i].format));
+ if (m_regs[i].kinds[eRegisterKindGDB] != LLDB_INVALID_REGNUM)
+ s.Printf(", gdb = %3u", m_regs[i].kinds[eRegisterKindGDB]);
+ if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
+ s.Printf(", dwarf = %3u", m_regs[i].kinds[eRegisterKindDWARF]);
+ if (m_regs[i].kinds[eRegisterKindGCC] != LLDB_INVALID_REGNUM)
+ s.Printf(", gcc = %3u", m_regs[i].kinds[eRegisterKindGCC]);
+ if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)
+ s.Printf(", generic = %3u", m_regs[i].kinds[eRegisterKindGeneric]);
+ if (m_regs[i].alt_name)
+ s.Printf(", alt-name = %s", m_regs[i].alt_name);
+ if (m_regs[i].value_regs)
+ {
+ s.Printf(", value_regs = [ ");
+ for (size_t j=0; m_regs[i].value_regs[j] != LLDB_INVALID_REGNUM; ++j)
+ {
+ s.Printf("%s ", m_regs[m_regs[i].value_regs[j]].name);
+ }
+ s.Printf("]");
+ }
+ if (m_regs[i].invalidate_regs)
+ {
+ s.Printf(", invalidate_regs = [ ");
+ for (size_t j=0; m_regs[i].invalidate_regs[j] != LLDB_INVALID_REGNUM; ++j)
+ {
+ s.Printf("%s ", m_regs[m_regs[i].invalidate_regs[j]].name);
+ }
+ s.Printf("]");
+ }
+ s.EOL();
+ }
+
+ const size_t num_sets = m_sets.size();
+ s.Printf("%p: DynamicRegisterInfo contains %zu register sets:\n", this, num_sets);
+ for (size_t i=0; i<num_sets; ++i)
+ {
+ s.Printf("set[%zu] name = %s, regs = [", 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);
+ }
+ s.Printf("]\n");
+ }
+}
+
+
+
+lldb_private::RegisterInfo *
+DynamicRegisterInfo::GetRegisterInfo (const lldb_private::ConstString &reg_name)
+{
+ for (auto &reg_info : m_regs)
+ {
+ // We can use pointer comparison since we used a ConstString to set
+ // the "name" member in AddRegister()
+ if (reg_info.name == reg_name.GetCString())
+ {
+ return &reg_info;
+ }
+ }
+ return NULL;
}
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
index a11cd333545f..a41c77e49f9d 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -13,6 +13,7 @@
// C Includes
// C++ Includes
#include <vector>
+#include <map>
// Other libraries and framework includes
// Project includes
@@ -24,13 +25,15 @@ class DynamicRegisterInfo
public:
DynamicRegisterInfo ();
- DynamicRegisterInfo (const lldb_private::PythonDictionary &dict);
+ DynamicRegisterInfo (const lldb_private::PythonDictionary &dict,
+ lldb::ByteOrder byte_order);
virtual
~DynamicRegisterInfo ();
size_t
- SetRegisterInfo (const lldb_private::PythonDictionary &dict);
+ SetRegisterInfo (const lldb_private::PythonDictionary &dict,
+ lldb::ByteOrder byte_order);
void
AddRegister (lldb_private::RegisterInfo &reg_info,
@@ -63,6 +66,9 @@ public:
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const;
void
+ Dump () const;
+
+ void
Clear();
protected:
@@ -74,12 +80,19 @@ protected:
typedef std::vector <uint32_t> reg_num_collection;
typedef std::vector <reg_num_collection> set_reg_num_collection;
typedef std::vector <lldb_private::ConstString> name_collection;
+ typedef std::map<uint32_t, reg_num_collection> reg_to_regs_map;
+
+ lldb_private::RegisterInfo *
+ GetRegisterInfo (const lldb_private::ConstString &reg_name);
reg_collection m_regs;
set_collection m_sets;
set_reg_num_collection m_set_reg_nums;
name_collection m_set_names;
+ reg_to_regs_map m_value_regs_map;
+ reg_to_regs_map m_invalidate_regs_map;
size_t m_reg_data_byte_size; // The number of bytes required to store all registers
+ bool m_finalized;
};
#endif // lldb_DynamicRegisterInfo_h_
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 499d6d766150..8b22d6457ada 100644
--- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -17,8 +17,19 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
+#include "lldb/Host/Config.h"
+#ifndef LLDB_DISABLE_POSIX
#include <sys/mman.h>
+#else
+// define them
+#define PROT_NONE 0
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define PROT_EXEC 4
+#define MAP_PRIVATE 2
+#define MAP_ANON 0x1000
+#endif
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 1ffc30da5762..c19aec3a02c7 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -369,8 +369,13 @@ RegisterContextLLDB::InitializeNonZerothFrame()
return;
}
+ bool resolve_tail_call_address = true; // m_current_pc can be one past the address range of the function...
+ uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress (m_current_pc,
+ eSymbolContextFunction | eSymbolContextSymbol,
+ 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 ((pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+ if ((resolved_scope & eSymbolContextSymbol) == eSymbolContextSymbol)
{
m_sym_ctx_valid = true;
}
@@ -387,35 +392,18 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (m_sym_ctx_valid == false)
decr_pc_and_recompute_addr_range = true;
- // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp),
- // and our "current" pc is the start of a function...
+ // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp), and
+ // our "current" pc is the start of a function or our "current" pc is one past the end of a function...
if (m_sym_ctx_valid
&& GetNextFrame()->m_frame_type != eSigtrampFrame
&& GetNextFrame()->m_frame_type != eDebuggerFrame
&& addr_range.GetBaseAddress().IsValid()
- && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection()
- && addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset())
+ && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection())
{
- decr_pc_and_recompute_addr_range = true;
- }
-
- // We need to back up the pc by 1 byte and re-search for the Symbol to handle the case where the "saved pc"
- // value is pointing to the next function, e.g. if a function ends with a CALL instruction.
- // FIXME this may need to be an architectural-dependent behavior; if so we'll need to add a member function
- // to the ABI plugin and consult that.
- if (decr_pc_and_recompute_addr_range)
- {
- Address temporary_pc(m_current_pc);
- temporary_pc.SetOffset(m_current_pc.GetOffset() - 1);
- m_sym_ctx.Clear(false);
- m_sym_ctx_valid = false;
- if ((pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+ if (addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset() ||
+ addr_range.GetBaseAddress().GetOffset() + addr_range.GetByteSize() == m_current_pc.GetOffset())
{
- m_sym_ctx_valid = true;
- }
- if (!m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range))
- {
- m_sym_ctx_valid = false;
+ decr_pc_and_recompute_addr_range = true;
}
}
@@ -632,6 +620,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp);
}
+ else
+ {
+ UnwindLogMsg ("unable to get architectural default UnwindPlan from ABI plugin");
+ }
bool behaves_like_zeroth_frame = false;
if (IsFrameZero ()
@@ -648,9 +640,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// in the zeroth frame, we need to use the "unwind at first instruction" arch default UnwindPlan
// Also, if this Process can report on memory region attributes, any non-executable region means
// we jumped through a bad function pointer - handle the same way as 0x0.
- // Note, if the symbol context has a function for the symbol, then we don't need to do this check.
+ // 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.function == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid())
+ if ((!m_sym_ctx_valid || 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());
@@ -757,8 +750,24 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
return unwind_plan_sp;
}
+ // If we're on the first instruction of a function, and we have an architectural default UnwindPlan
+ // for the initial instruction of a function, use that.
+ if (m_current_offset_backed_up_one == 0)
+ {
+ unwind_plan_sp = func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry (m_thread);
+ if (unwind_plan_sp)
+ {
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
+ return unwind_plan_sp;
+ }
+ }
+
// If nothing else, use the architectural default UnwindPlan and hope that does the job.
- UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString());
+ if (arch_default_unwind_plan_sp)
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString());
+ else
+ UnwindLogMsg ("Unable to find any UnwindPlan for full unwind of this frame.");
+
return arch_default_unwind_plan_sp;
}
@@ -1101,7 +1110,8 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
if (reg_info && abi->RegisterIsVolatile (reg_info))
{
- UnwindLogMsg ("did not supply reg location for %d because it is volatile", lldb_regnum);
+ UnwindLogMsg ("did not supply reg location for %d (%s) because it is volatile",
+ lldb_regnum, reg_info->name ? reg_info->name : "??");
return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
}
}
@@ -1186,7 +1196,8 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
unwindplan_regloc.GetDWARFExpressionLength(),
process->GetByteOrder(), process->GetAddressByteSize());
- DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
+ ModuleSP opcode_ctx;
+ DWARFExpression dwarfexpr (opcode_ctx, dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind (unwindplan_registerkind);
Value result;
Error error;
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
index 2c3eee452488..5b6d9fe9f3bb 100644
--- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
@@ -147,9 +147,9 @@ RegisterContextMacOSXFrameBackchain::ReadRegister (const RegisterInfo *reg_info,
}
break;
- // TOOD: need a better way to detect when "long double" types are
+ // TOOD: need a better way to detect when "long double" types are
// the same bytes size as "double"
-#if !defined(__arm__)
+#if !defined(__arm__) && !defined(_MSC_VER) && !defined(__mips__)
case sizeof (long double):
if (sizeof (long double) == sizeof(uint32_t))
{
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 0eea00363498..552ae501bd21 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -185,21 +185,7 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
}
goto unwind_done;
}
- if (!m_frames.empty())
- {
- if (m_frames.back()->start_pc == cursor_sp->start_pc)
- {
- if (m_frames.back()->cfa == cursor_sp->cfa)
- goto unwind_done; // Infinite loop where the current cursor is the same as the previous one...
- else if (abi && abi->StackUsesFrames())
- {
- // We might have a CFA that is not using the frame pointer and
- // we want to validate that the frame pointer is valid.
- if (reg_ctx_sp->GetFP() == 0)
- goto unwind_done;
- }
- }
- }
+
cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp;
m_frames.push_back (cursor_sp);
return true;
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index dd553ce36c89..acb3154f6290 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -338,9 +338,9 @@ ProcessElfCore::GetImageInfoAddress()
{
Target *target = &GetTarget();
ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
- Address addr = obj_file->GetImageInfoAddress();
+ Address addr = obj_file->GetImageInfoAddress(target);
- if (addr.IsValid())
+ if (addr.IsValid())
return addr.GetLoadAddress(target);
return LLDB_INVALID_ADDRESS;
}
@@ -363,13 +363,6 @@ enum {
NT_FREEBSD_PROCSTAT_AUXV = 16
};
-/// Align the given value to next boundary specified by the alignment bytes
-static uint32_t
-AlignToNext(uint32_t value, int alignment_bytes)
-{
- return (value + alignment_bytes - 1) & ~(alignment_bytes - 1);
-}
-
/// Note Structure found in ELF core dumps.
/// This is PT_NOTE type program/segments in the core file.
struct ELFNote
@@ -421,7 +414,7 @@ struct ELFNote
}
}
- const char *cstr = data.GetCStr(offset, AlignToNext(n_namesz, 4));
+ const char *cstr = data.GetCStr(offset, llvm::RoundUpToAlignment(n_namesz, 4));
if (cstr == NULL)
{
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
@@ -441,7 +434,8 @@ ParseFreeBSDPrStatus(ThreadData *thread_data, DataExtractor &data,
ArchSpec &arch)
{
lldb::offset_t offset = 0;
- bool have_padding = (arch.GetMachine() == llvm::Triple::x86_64);
+ bool have_padding = (arch.GetMachine() == llvm::Triple::mips64 ||
+ arch.GetMachine() == llvm::Triple::x86_64);
int pr_version = data.GetU32(&offset);
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
@@ -525,7 +519,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
size_t note_start, note_size;
note_start = offset;
- note_size = AlignToNext(note.n_descsz, 4);
+ note_size = llvm::RoundUpToAlignment(note.n_descsz, 4);
// Store the NOTE information in the current thread
DataExtractor note_data (segment_data, note_start, note_size);
diff --git a/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.cpp
deleted file mode 100644
index 6210175f9a7f..000000000000
--- a/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-//===-- RegisterContextCoreFreeBSD_x86_64.cpp -------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Target/Thread.h"
-#include "RegisterContextCoreFreeBSD_x86_64.h"
-
-RegisterContextCoreFreeBSD_x86_64::RegisterContextCoreFreeBSD_x86_64(Thread &thread,
- const DataExtractor &gpregset, const DataExtractor &fpregset)
- : RegisterContextFreeBSD_x86_64(thread, 0)
-{
- size_t size, len;
-
- size = GetGPRSize();
- m_gpregset = new uint8_t[size];
- len = gpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_gpregset);
- assert(len == size);
-}
-
-RegisterContextCoreFreeBSD_x86_64::~RegisterContextCoreFreeBSD_x86_64()
-{
- delete [] m_gpregset;
-}
-
-bool
-RegisterContextCoreFreeBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
-{
- value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
- return true;
-}
-
-bool
-RegisterContextCoreFreeBSD_x86_64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
-{
- return false;
-}
-
-bool
-RegisterContextCoreFreeBSD_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
-{
- return false;
-}
-
-bool
-RegisterContextCoreFreeBSD_x86_64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
-{
- return false;
-}
-
-bool
-RegisterContextCoreFreeBSD_x86_64::UpdateAfterBreakpoint()
-{
- return false;
-}
-
-bool
-RegisterContextCoreFreeBSD_x86_64::HardwareSingleStep(bool enable)
-{
- return false;
-}
-
diff --git a/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.h
deleted file mode 100644
index acd594a6e666..000000000000
--- a/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===-- RegisterContextCoreFreeBSD_x86_64.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_RegisterContextCoreFreeBSD_x86_64_H_
-#define liblldb_RegisterContextCoreFreeBSD_x86_64_H_
-
-#include "Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h"
-
-using namespace lldb_private;
-
-class RegisterContextCoreFreeBSD_x86_64: public RegisterContextFreeBSD_x86_64
-{
-public:
- RegisterContextCoreFreeBSD_x86_64 (Thread &thread, const DataExtractor &gpregset,
- const DataExtractor &fpregset);
-
- ~RegisterContextCoreFreeBSD_x86_64();
-
- virtual bool
- ReadRegister(const RegisterInfo *reg_info, RegisterValue &value);
-
- bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
-
- virtual bool
- WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value);
-
- bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
-
- bool
- HardwareSingleStep(bool enable);
-
- bool
- UpdateAfterBreakpoint();
-
-private:
- uint8_t *m_gpregset;
-};
-
-#endif // #ifndef liblldb_RegisterContextCoreFreeBSD_x86_64_H_
diff --git a/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.cpp
deleted file mode 100644
index d9e3f6d5f90b..000000000000
--- a/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-//===-- RegisterContextCoreLinux_x86_64.cpp -------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Target/Thread.h"
-#include "RegisterContextCoreLinux_x86_64.h"
-
-RegisterContextCoreLinux_x86_64::RegisterContextCoreLinux_x86_64(Thread &thread,
- const DataExtractor &gpregset,
- const DataExtractor &fpregset)
- : RegisterContextLinux_x86_64(thread, 0)
-{
- size_t size, len;
-
- size = GetGPRSize();
- m_gpregset = new uint8_t[size];
- len = gpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_gpregset);
- assert(len == size);
-}
-
-RegisterContextCoreLinux_x86_64::~RegisterContextCoreLinux_x86_64()
-{
- delete [] m_gpregset;
-}
-
-bool
-RegisterContextCoreLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
-{
- value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
- return true;
-}
-
-bool
-RegisterContextCoreLinux_x86_64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
-{
- return false;
-}
-
-bool
-RegisterContextCoreLinux_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
-{
- return false;
-}
-
-bool
-RegisterContextCoreLinux_x86_64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
-{
- return false;
-}
-
-bool
-RegisterContextCoreLinux_x86_64::UpdateAfterBreakpoint()
-{
- return false;
-}
-
-bool
-RegisterContextCoreLinux_x86_64::HardwareSingleStep(bool enable)
-{
- return false;
-}
diff --git a/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.h
deleted file mode 100644
index 9cf545afd56a..000000000000
--- a/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===-- RegisterContextCoreLinux_x86_64.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_RegisterContextCoreLinux_x86_64_H_
-#define liblldb_RegisterContextCoreLinux_x86_64_H_
-
-#include "Plugins/Process/POSIX/RegisterContextLinux_x86_64.h"
-
-using namespace lldb_private;
-
-class RegisterContextCoreLinux_x86_64: public RegisterContextLinux_x86_64
-{
-public:
- RegisterContextCoreLinux_x86_64 (Thread &thread, const DataExtractor &gpregset,
- const DataExtractor &fpregset);
-
- ~RegisterContextCoreLinux_x86_64();
-
- virtual bool
- ReadRegister(const RegisterInfo *reg_info, RegisterValue &value);
-
- bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
-
- virtual bool
- WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value);
-
- bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
-
- bool
- HardwareSingleStep(bool enable);
-
- bool
- UpdateAfterBreakpoint();
-
-protected:
- bool
- ReadFPR()
- {
- assert(0);
- }
-
-private:
- uint8_t *m_gpregset;
-};
-
-#endif // #ifndef liblldb_RegisterContextCoreLinux_x86_64_H_
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
new file mode 100644
index 000000000000..b95a51130ca7
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
@@ -0,0 +1,94 @@
+//===-- RegisterContextCorePOSIX_mips64.cpp ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Target/Thread.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterContextPOSIXCore_mips64.h"
+
+using namespace lldb_private;
+
+RegisterContextCorePOSIX_mips64::RegisterContextCorePOSIX_mips64(Thread &thread,
+ RegisterInfoInterface *register_info,
+ const DataExtractor &gpregset,
+ 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);
+ }
+}
+
+RegisterContextCorePOSIX_mips64::~RegisterContextCorePOSIX_mips64()
+{
+}
+
+bool
+RegisterContextCorePOSIX_mips64::ReadGPR()
+{
+ return true;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::ReadFPR()
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::WriteGPR()
+{
+ assert(0);
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::WriteFPR()
+{
+ assert(0);
+ return false;
+}
+
+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;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::HardwareSingleStep(bool enable)
+{
+ return false;
+}
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
new file mode 100644
index 000000000000..92e486bf2235
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
@@ -0,0 +1,58 @@
+//===-- RegisterContextCorePOSIX_mips64.h ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextCorePOSIX_mips64_H_
+#define liblldb_RegisterContextCorePOSIX_mips64_H_
+
+#include "Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h"
+
+class RegisterContextCorePOSIX_mips64 :
+ public RegisterContextPOSIX_mips64
+{
+public:
+ RegisterContextCorePOSIX_mips64 (lldb_private::Thread &thread,
+ RegisterInfoInterface *register_info,
+ const lldb_private::DataExtractor &gpregset,
+ const lldb_private::DataExtractor &fpregset);
+
+ ~RegisterContextCorePOSIX_mips64();
+
+ virtual bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+ virtual bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+ bool
+ HardwareSingleStep(bool enable);
+
+protected:
+ bool
+ ReadGPR();
+
+ bool
+ ReadFPR();
+
+ bool
+ WriteGPR();
+
+ bool
+ WriteFPR();
+
+private:
+ uint64_t m_reg[40];
+};
+
+#endif // #ifndef liblldb_RegisterContextCorePOSIX_mips64_H_
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
new file mode 100644
index 000000000000..610506c20a0b
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
@@ -0,0 +1,92 @@
+//===-- RegisterContextCorePOSIX_x86_64.cpp ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Target/Thread.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterContextPOSIXCore_x86_64.h"
+
+using namespace lldb_private;
+
+RegisterContextCorePOSIX_x86_64::RegisterContextCorePOSIX_x86_64(Thread &thread,
+ RegisterInfoInterface *register_info,
+ const DataExtractor &gpregset,
+ const DataExtractor &fpregset)
+ : RegisterContextPOSIX_x86 (thread, 0, register_info)
+{
+ size_t size, len;
+
+ size = GetGPRSize();
+ m_gpregset = new uint8_t[size];
+ len = gpregset.ExtractBytes (0, size, lldb::eByteOrderLittle, m_gpregset);
+ assert(len == size);
+}
+
+RegisterContextCorePOSIX_x86_64::~RegisterContextCorePOSIX_x86_64()
+{
+ delete [] m_gpregset;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::ReadGPR()
+{
+ return m_gpregset != NULL;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::ReadFPR()
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::WriteGPR()
+{
+ assert(0);
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::WriteFPR()
+{
+ assert(0);
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+ value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
+ return true;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::HardwareSingleStep(bool enable)
+{
+ return false;
+}
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
new file mode 100644
index 000000000000..d4ea14fab7b1
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
@@ -0,0 +1,58 @@
+//===-- RegisterContextCorePOSIX_x86_64.h ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextCorePOSIX_x86_64_H_
+#define liblldb_RegisterContextCorePOSIX_x86_64_H_
+
+#include "Plugins/Process/POSIX/RegisterContextPOSIX_x86.h"
+
+class RegisterContextCorePOSIX_x86_64 :
+ public RegisterContextPOSIX_x86
+{
+public:
+ RegisterContextCorePOSIX_x86_64 (lldb_private::Thread &thread,
+ RegisterInfoInterface *register_info,
+ const lldb_private::DataExtractor &gpregset,
+ const lldb_private::DataExtractor &fpregset);
+
+ ~RegisterContextCorePOSIX_x86_64();
+
+ virtual bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+ virtual bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+ bool
+ HardwareSingleStep(bool enable);
+
+protected:
+ bool
+ ReadGPR();
+
+ bool
+ ReadFPR();
+
+ bool
+ WriteGPR();
+
+ bool
+ WriteFPR();
+
+private:
+ uint8_t *m_gpregset;
+};
+
+#endif // #ifndef liblldb_RegisterContextCorePOSIX_x86_64_H_
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index a7229663dc89..3bda86dc0f73 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -16,8 +16,11 @@
#include "ThreadElfCore.h"
#include "ProcessElfCore.h"
-#include "RegisterContextCoreFreeBSD_x86_64.h"
-#include "RegisterContextCoreLinux_x86_64.h"
+#include "RegisterContextLinux_x86_64.h"
+#include "RegisterContextFreeBSD_mips64.h"
+#include "RegisterContextFreeBSD_x86_64.h"
+#include "RegisterContextPOSIXCore_mips64.h"
+#include "RegisterContextPOSIXCore_x86_64.h"
using namespace lldb;
using namespace lldb_private;
@@ -84,14 +87,28 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
ArchSpec arch = process->GetArchitecture();
switch (arch.GetMachine())
{
+ case llvm::Triple::mips64:
+ switch (arch.GetTriple().getOS())
+ {
+ case llvm::Triple::FreeBSD:
+ m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, new RegisterContextFreeBSD_mips64(arch), m_gpregset_data, m_fpregset_data));
+ break;
+ default:
+ if (log)
+ log->Printf ("elf-core::%s:: OS(%d) not supported",
+ __FUNCTION__, arch.GetTriple().getOS());
+ assert (false && "OS not supported");
+ break;
+ }
+ break;
case llvm::Triple::x86_64:
switch (arch.GetTriple().getOS())
{
case llvm::Triple::FreeBSD:
- m_thread_reg_ctx_sp.reset(new RegisterContextCoreFreeBSD_x86_64 (*this, m_gpregset_data, m_fpregset_data));
+ m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, new RegisterContextFreeBSD_x86_64(arch), m_gpregset_data, m_fpregset_data));
break;
case llvm::Triple::Linux:
- m_thread_reg_ctx_sp.reset(new RegisterContextCoreLinux_x86_64 (*this, m_gpregset_data, m_fpregset_data));
+ m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, new RegisterContextLinux_x86_64(arch), m_gpregset_data, m_fpregset_data));
break;
default:
if (log)
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h
index ca6339d7ec9d..2661edfa50cd 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.h
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.h
@@ -29,6 +29,10 @@ struct compat_timeval
#define ELFLINUXPRSTATUS64_SIZE (112)
#define ELFLINUXPRPSINFO64_SIZE (132)
+#undef si_signo
+#undef si_code
+#undef si_errno
+
struct ELFLinuxPrStatus
{
int32_t si_signo;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index d7efdf2302d8..f67e1b5d49c3 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -133,7 +133,11 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
const char *listener_name,
bool is_platform) :
Communication(comm_name),
+#ifdef LLDB_CONFIGURATION_DEBUG
+ m_packet_timeout (1000),
+#else
m_packet_timeout (1),
+#endif
m_sequence_mutex (Mutex::eMutexTypeRecursive),
m_public_is_running (false),
m_private_is_running (false),
@@ -173,7 +177,7 @@ GDBRemoteCommunication::SendAck ()
char ch = '+';
const size_t bytes_written = Write (&ch, 1, status, NULL);
if (log)
- log->Printf ("<%4zu> send packet: %c", bytes_written, ch);
+ log->Printf ("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
return bytes_written;
}
@@ -186,7 +190,7 @@ GDBRemoteCommunication::SendNack ()
char ch = '-';
const size_t bytes_written = Write (&ch, 1, status, NULL);
if (log)
- log->Printf ("<%4zu> send packet: %c", bytes_written, ch);
+ log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
return bytes_written;
}
@@ -222,7 +226,7 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le
if (!m_history.DidDumpToLog ())
m_history.Dump (log);
- log->Printf ("<%4zu> send packet: %.*s", bytes_written, (int)packet.GetSize(), packet.GetData());
+ log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)packet.GetSize(), packet.GetData());
}
m_history.AddPacket (packet.GetString(), packet.GetSize(), History::ePacketTypeSend, bytes_written);
@@ -456,13 +460,38 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
if (!m_history.DidDumpToLog ())
m_history.Dump (log);
- log->Printf ("<%4zu> read packet: %.*s", total_length, (int)(total_length), m_bytes.c_str());
+ 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);
- packet_str.assign (m_bytes, content_start, content_length);
-
+ // Clear packet_str in case there is some existing data in it.
+ packet_str.clear();
+ // Copy the packet from m_bytes to packet_str expanding the
+ // 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)
+ {
+ if (*c == '*')
+ {
+ // '*' indicates RLE. Next character will give us the
+ // repeat count and previous character is what is to be
+ // repeated.
+ char char_to_repeat = packet_str.back();
+ // Number of time the previous character is repeated
+ int repeat_count = *++c + 3 - ' ';
+ // We have the char_to_repeat and repeat_count. Now push
+ // it in the packet.
+ for (int i = 0; i < repeat_count; ++i)
+ packet_str.push_back(char_to_repeat);
+ }
+ else
+ {
+ packet_str.push_back(*c);
+ }
+ }
+
if (m_bytes[0] == '$')
{
assert (checksum_idx < m_bytes.size());
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index ca594a8f3fd5..2ac7d20c6c60 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -11,6 +11,8 @@
#include "GDBRemoteCommunicationClient.h"
// C Includes
+#include <sys/stat.h>
+
// C++ Includes
#include <sstream>
@@ -20,6 +22,7 @@
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
+#include "lldb/Core/StreamGDBRemote.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/Host.h"
@@ -29,10 +32,15 @@
#include "Utility/StringExtractorGDBRemote.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
+#include "lldb/Host/Config.h"
using namespace lldb;
using namespace lldb_private;
+#ifdef LLDB_DISABLE_POSIX
+#define SIGSTOP 17
+#endif
+
//----------------------------------------------------------------------
// GDBRemoteCommunicationClient constructor
//----------------------------------------------------------------------
@@ -56,6 +64,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
m_attach_or_wait_reply(eLazyBoolCalculate),
m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
+ m_supports_p (eLazyBoolCalculate),
m_supports_qProcessInfoPID (true),
m_supports_qfProcessInfo (true),
m_supports_qUserName (true),
@@ -66,6 +75,8 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_supports_z2 (true),
m_supports_z3 (true),
m_supports_z4 (true),
+ m_supports_QEnvironment (true),
+ m_supports_QEnvironmentHexEncoded (true),
m_curr_tid (LLDB_INVALID_THREAD_ID),
m_curr_tid_run (LLDB_INVALID_THREAD_ID),
m_num_supported_hardware_watchpoints (0),
@@ -79,7 +90,11 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_process_arch(),
m_os_version_major (UINT32_MAX),
m_os_version_minor (UINT32_MAX),
- m_os_version_update (UINT32_MAX)
+ m_os_version_update (UINT32_MAX),
+ m_os_build (),
+ m_os_kernel (),
+ m_hostname (),
+ m_default_packet_timeout (0)
{
}
@@ -192,6 +207,7 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_vCont_C = eLazyBoolCalculate;
m_supports_vCont_s = eLazyBoolCalculate;
m_supports_vCont_S = eLazyBoolCalculate;
+ m_supports_p = eLazyBoolCalculate;
m_qHostInfo_is_valid = eLazyBoolCalculate;
m_qProcessInfo_is_valid = eLazyBoolCalculate;
m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
@@ -209,6 +225,8 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_z2 = true;
m_supports_z3 = true;
m_supports_z4 = true;
+ m_supports_QEnvironment = true;
+ m_supports_QEnvironmentHexEncoded = true;
m_host_arch.Clear();
m_process_arch.Clear();
}
@@ -287,6 +305,32 @@ GDBRemoteCommunicationClient::GetVContSupported (char flavor)
return false;
}
+// Check if the target supports 'p' packet. It sends out a 'p'
+// packet and checks the response. A normal packet will tell us
+// that support is available.
+//
+// Takes a valid thread ID because p needs to apply to a thread.
+bool
+GDBRemoteCommunicationClient::GetpPacketSupported (lldb::tid_t tid)
+{
+ if (m_supports_p == eLazyBoolCalculate)
+ {
+ StringExtractorGDBRemote response;
+ m_supports_p = eLazyBoolNo;
+ char packet[256];
+ if (GetThreadSuffixSupported())
+ snprintf(packet, sizeof(packet), "p0;thread:%" PRIx64 ";", tid);
+ else
+ snprintf(packet, sizeof(packet), "p0");
+
+ if (SendPacketAndWaitForResponse(packet, response, false))
+ {
+ if (response.IsNormalResponse())
+ m_supports_p = eLazyBoolYes;
+ }
+ }
+ return m_supports_p;
+}
size_t
GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
@@ -978,15 +1022,61 @@ GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_valu
if (name_equal_value && name_equal_value[0])
{
StreamString packet;
- packet.Printf("QEnvironment:%s", name_equal_value);
+ bool send_hex_encoding = false;
+ for (const char *p = name_equal_value; *p != '\0' && send_hex_encoding == false; ++p)
+ {
+ if (isprint(*p))
+ {
+ switch (*p)
+ {
+ case '$':
+ case '#':
+ send_hex_encoding = true;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // We have non printable characters, lets hex encode this...
+ send_hex_encoding = true;
+ }
+ }
+
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ if (send_hex_encoding)
{
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
+ if (m_supports_QEnvironmentHexEncoded)
+ {
+ packet.PutCString("QEnvironmentHexEncoded:");
+ packet.PutBytesAsRawHex8 (name_equal_value, strlen(name_equal_value));
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
+ if (response.IsUnsupportedResponse())
+ m_supports_QEnvironmentHexEncoded = false;
+ }
+ }
+
+ }
+ else if (m_supports_QEnvironment)
+ {
+ packet.Printf("QEnvironment:%s", name_equal_value);
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
+ if (response.IsUnsupportedResponse())
+ m_supports_QEnvironment = false;
+ }
}
}
return -1;
@@ -1213,6 +1303,15 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
else
--num_keys_decoded;
}
+ else if (name.compare("default_packet_timeout") == 0)
+ {
+ m_default_packet_timeout = Args::StringToUInt32(value.c_str(), 0);
+ if (m_default_packet_timeout > 0)
+ {
+ SetPacketTimeout(m_default_packet_timeout);
+ ++num_keys_decoded;
+ }
+ }
}
@@ -1347,6 +1446,14 @@ GDBRemoteCommunicationClient::GetHostArchitecture ()
return m_host_arch;
}
+uint32_t
+GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout ()
+{
+ if (m_qHostInfo_is_valid == eLazyBoolCalculate)
+ GetHostInfo ();
+ return m_default_packet_timeout;
+}
+
addr_t
GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions)
{
@@ -2132,21 +2239,37 @@ GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t
}
uint16_t
-GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort ()
+GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
{
+ pid = LLDB_INVALID_PROCESS_ID;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qLaunchGDBServer", strlen("qLaunchGDBServer"), response, false))
+ StreamString stream;
+ stream.PutCString("qLaunchGDBServer:port:0;");
+ std::string hostname;
+ if (Host::GetHostname (hostname))
+ {
+ // Make the GDB server we launch only accept connections from this host
+ stream.Printf("host:%s;", hostname.c_str());
+ }
+ else
+ {
+ // Make the GDB server we launch accept connections from any host since we can't figure out the hostname
+ stream.Printf("host:*;");
+ }
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
std::string name;
std::string value;
uint16_t port = 0;
- //lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
while (response.GetNameColonValue(name, value))
{
- if (name.size() == 4 && name.compare("port") == 0)
+ if (name.compare("port") == 0)
port = Args::StringToUInt32(value.c_str(), 0, 0);
-// if (name.size() == 3 && name.compare("pid") == 0)
-// pid = Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
+ else if (name.compare("pid") == 0)
+ pid = Args::StringToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
}
return port;
}
@@ -2154,6 +2277,23 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort ()
}
bool
+GDBRemoteCommunicationClient::KillSpawnedProcess (lldb::pid_t pid)
+{
+ StreamString stream;
+ stream.Printf ("qKillSpawnedProcess:%" PRId64 , pid);
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.IsOKResponse())
+ return true;
+ }
+ return false;
+}
+
+bool
GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid)
{
if (m_curr_tid == tid)
@@ -2222,7 +2362,9 @@ GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtracto
assert (packet_len < (int)sizeof(packet));
if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
- if (response.IsNormalResponse())
+ if (response.IsUnsupportedResponse())
+ m_supports_qThreadStopInfo = false;
+ else if (response.IsNormalResponse())
return true;
else
return false;
@@ -2232,8 +2374,6 @@ GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtracto
m_supports_qThreadStopInfo = false;
}
}
-// if (SetCurrentThread (tid))
-// return GetStopReply (response);
return false;
}
@@ -2346,3 +2486,326 @@ GDBRemoteCommunicationClient::GetShlibInfoAddr()
return LLDB_INVALID_ADDRESS;
}
+lldb_private::Error
+GDBRemoteCommunicationClient::RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("qPlatform_RunCommand:");
+ stream.PutBytesAsRawHex8(command, strlen(command));
+ stream.PutChar(',');
+ stream.PutHex32(timeout_sec);
+ if (working_dir && *working_dir)
+ {
+ stream.PutChar(',');
+ stream.PutBytesAsRawHex8(working_dir, strlen(working_dir));
+ }
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return Error("malformed reply");
+ if (response.GetChar() != ',')
+ return Error("malformed reply");
+ uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX);
+ if (exitcode == UINT32_MAX)
+ return Error("unable to run remote process");
+ else if (status_ptr)
+ *status_ptr = exitcode;
+ if (response.GetChar() != ',')
+ return Error("malformed reply");
+ uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX);
+ if (signo_ptr)
+ *signo_ptr = signo;
+ if (response.GetChar() != ',')
+ return Error("malformed reply");
+ std::string output;
+ response.GetEscapedBinaryData(output);
+ if (command_output)
+ command_output->assign(output);
+ return Error();
+ }
+ return Error("unable to send packet");
+}
+
+uint32_t
+GDBRemoteCommunicationClient::MakeDirectory (const std::string &path,
+ mode_t mode)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("qPlatform_IO_MkDir:");
+ stream.PutHex32(mode);
+ stream.PutChar(',');
+ stream.PutBytesAsRawHex8(path.c_str(), path.size());
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ return response.GetHexMaxU32(false, UINT32_MAX);
+ }
+ return UINT32_MAX;
+
+}
+
+static uint64_t
+ParseHostIOPacketResponse (StringExtractorGDBRemote &response,
+ uint64_t fail_result,
+ Error &error)
+{
+ response.SetFilePos(0);
+ if (response.GetChar() != 'F')
+ return fail_result;
+ int32_t result = response.GetS32 (-2);
+ if (result == -2)
+ return fail_result;
+ if (response.GetChar() == ',')
+ {
+ int result_errno = response.GetS32 (-2);
+ if (result_errno != -2)
+ error.SetError(result_errno, eErrorTypePOSIX);
+ else
+ error.SetError(-1, eErrorTypeGeneric);
+ }
+ else
+ error.Clear();
+ return result;
+}
+lldb::user_id_t
+GDBRemoteCommunicationClient::OpenFile (const lldb_private::FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:open:");
+ std::string path (file_spec.GetPath());
+ if (path.empty())
+ return UINT64_MAX;
+ stream.PutCStringAsRawHex8(path.c_str());
+ stream.PutChar(',');
+ const uint32_t posix_open_flags = File::ConvertOpenOptionsForPOSIXOpen(flags);
+ stream.PutHex32(posix_open_flags);
+ stream.PutChar(',');
+ stream.PutHex32(mode);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ return ParseHostIOPacketResponse (response, UINT64_MAX, error);
+ }
+ return UINT64_MAX;
+}
+
+bool
+GDBRemoteCommunicationClient::CloseFile (lldb::user_id_t fd,
+ Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.Printf("vFile:close:%i", (int)fd);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ return ParseHostIOPacketResponse (response, -1, error) == 0;
+ }
+ return false;
+}
+
+// Extension of host I/O packets to get the file size.
+lldb::user_id_t
+GDBRemoteCommunicationClient::GetFileSize (const lldb_private::FileSpec& file_spec)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:size:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return UINT64_MAX;
+ uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX);
+ return retcode;
+ }
+ return UINT64_MAX;
+}
+
+uint32_t
+GDBRemoteCommunicationClient::GetFilePermissions(const lldb_private::FileSpec& file_spec, Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:mode:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ {
+ error.SetErrorStringWithFormat ("invalid response to '%s' packet", packet);
+ return 0;
+ }
+ const uint32_t mode = response.GetS32(-1);
+ if (mode == -1)
+ {
+ if (response.GetChar() == ',')
+ {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ else
+ error.SetErrorToGenericError();
+ }
+ }
+ else
+ error.Clear();
+ return mode & (S_IRWXU|S_IRWXG|S_IRWXO);
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("failed to send '%s' packet", packet);
+ }
+ return 0;
+}
+
+uint64_t
+GDBRemoteCommunicationClient::ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len, offset);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return 0;
+ uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX);
+ if (retcode == UINT32_MAX)
+ return retcode;
+ const char next = (response.Peek() ? *response.Peek() : 0);
+ if (next == ',')
+ return 0;
+ if (next == ';')
+ {
+ response.GetChar(); // skip the semicolon
+ std::string buffer;
+ if (response.GetEscapedBinaryData(buffer))
+ {
+ const uint64_t data_to_write = std::min<uint64_t>(dst_len, buffer.size());
+ if (data_to_write > 0)
+ memcpy(dst, &buffer[0], data_to_write);
+ return data_to_write;
+ }
+ }
+ }
+ return 0;
+}
+
+uint64_t
+GDBRemoteCommunicationClient::WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ Error &error)
+{
+ lldb_private::StreamGDBRemote stream;
+ stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset);
+ stream.PutEscapedBytes(src, src_len);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ {
+ error.SetErrorStringWithFormat("write file failed");
+ return 0;
+ }
+ uint64_t bytes_written = response.GetU64(UINT64_MAX);
+ if (bytes_written == UINT64_MAX)
+ {
+ error.SetErrorToGenericError();
+ if (response.GetChar() == ',')
+ {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ }
+ return 0;
+ }
+ return bytes_written;
+ }
+ else
+ {
+ error.SetErrorString ("failed to send vFile:pwrite packet");
+ }
+ return 0;
+}
+
+// Extension of host I/O packets to get whether a file exists.
+bool
+GDBRemoteCommunicationClient::GetFileExists (const lldb_private::FileSpec& file_spec)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:exists:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return false;
+ if (response.GetChar() != ',')
+ return false;
+ bool retcode = (response.GetChar() != '0');
+ return retcode;
+ }
+ return false;
+}
+
+bool
+GDBRemoteCommunicationClient::CalculateMD5 (const lldb_private::FileSpec& file_spec,
+ uint64_t &high,
+ uint64_t &low)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:MD5:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return false;
+ if (response.GetChar() != ',')
+ return false;
+ if (response.Peek() && *response.Peek() == 'x')
+ return false;
+ low = response.GetHexMaxU64(false, UINT64_MAX);
+ high = response.GetHexMaxU64(false, UINT64_MAX);
+ return true;
+ }
+ return false;
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 5bb8387b9094..d5535bbb1df3 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -89,7 +89,10 @@ public:
GetLaunchSuccess (std::string &error_str);
uint16_t
- LaunchGDBserverAndGetPort ();
+ LaunchGDBserverAndGetPort (lldb::pid_t &pid);
+
+ bool
+ KillSpawnedProcess (lldb::pid_t pid);
//------------------------------------------------------------------
/// Sends a GDB remote protocol 'A' packet that delivers program
@@ -217,6 +220,9 @@ public:
const lldb_private::ArchSpec &
GetHostArchitecture ();
+
+ uint32_t
+ GetHostDefaultPacketTimeout();
const lldb_private::ArchSpec &
GetProcessArchitecture ();
@@ -225,6 +231,9 @@ public:
GetVContSupported (char flavor);
bool
+ GetpPacketSupported (lldb::tid_t tid);
+
+ bool
GetVAttachOrWaitSupported ();
bool
@@ -347,10 +356,61 @@ public:
return m_interrupt_sent;
}
+ virtual lldb::user_id_t
+ OpenFile (const lldb_private::FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ lldb_private::Error &error);
+
+ virtual bool
+ CloseFile (lldb::user_id_t fd,
+ lldb_private::Error &error);
+
+ virtual lldb::user_id_t
+ GetFileSize (const lldb_private::FileSpec& file_spec);
+
+ virtual uint32_t
+ GetFilePermissions(const lldb_private::FileSpec& file_spec,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ lldb_private::Error &error);
+
+ virtual uint32_t
+ MakeDirectory (const std::string &path,
+ mode_t mode);
+
+ virtual bool
+ GetFileExists (const lldb_private::FileSpec& file_spec);
+
+ virtual lldb_private::Error
+ RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
+
+ virtual bool
+ CalculateMD5 (const lldb_private::FileSpec& file_spec,
+ uint64_t &high,
+ uint64_t &low);
+
std::string
HarmonizeThreadIdsForProfileData (ProcessGDBRemote *process,
StringExtractorGDBRemote &inputStringExtractor);
-
+
protected:
bool
@@ -377,6 +437,7 @@ protected:
lldb_private::LazyBool m_watchpoints_trigger_after_instruction;
lldb_private::LazyBool m_attach_or_wait_reply;
lldb_private::LazyBool m_prepare_for_reg_writing_reply;
+ lldb_private::LazyBool m_supports_p;
bool
m_supports_qProcessInfoPID:1,
@@ -388,7 +449,9 @@ protected:
m_supports_z1:1,
m_supports_z2:1,
m_supports_z3:1,
- m_supports_z4:1;
+ m_supports_z4:1,
+ m_supports_QEnvironment:1,
+ m_supports_QEnvironmentHexEncoded:1;
lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations
@@ -416,6 +479,7 @@ protected:
std::string m_os_build;
std::string m_os_kernel;
std::string m_hostname;
+ uint32_t m_default_packet_timeout;
bool
DecodeProcessInfoResponse (StringExtractorGDBRemote &response,
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 3a14e9fe759a..df036cdcc8e0 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -7,8 +7,10 @@
//
//===----------------------------------------------------------------------===//
+#include <errno.h>
#include "GDBRemoteCommunicationServer.h"
+#include "lldb/Core/StreamGDBRemote.h"
// C Includes
// C++ Includes
@@ -20,6 +22,7 @@
#include "lldb/Core/State.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/Endian.h"
+#include "lldb/Host/File.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Target/Process.h"
@@ -40,11 +43,31 @@ GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
m_async_thread (LLDB_INVALID_HOST_THREAD),
m_process_launch_info (),
m_process_launch_error (),
+ m_spawned_pids (),
+ m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
m_proc_infos (),
m_proc_infos_index (0),
m_lo_port_num (0),
- m_hi_port_num (0)
+ m_hi_port_num (0),
+ m_next_port (0),
+ m_use_port_range (false)
{
+ // We seldom need to override the port number that the debugserver process
+ // starts with. We just pass in 0 to let the system choose a random port.
+ // In rare situation where the need arises, use two environment variables
+ // to override.
+ uint16_t lo_port_num = 0;
+ uint16_t hi_port_num = 0;
+ const char *lo_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_LO_PORT");
+ if (lo_port_c_str)
+ lo_port_num = ::atoi(lo_port_c_str);
+ const char *hi_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_HI_PORT");
+ if (hi_port_c_str)
+ hi_port_num = ::atoi(hi_port_c_str);
+ if (lo_port_num && hi_port_num && lo_port_num < hi_port_num)
+ {
+ SetPortRange(lo_port_num, hi_port_num);
+ }
}
//----------------------------------------------------------------------
@@ -65,7 +88,7 @@ GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
//
// StringExtractorGDBRemote packet;
-//
+//
// while ()
// {
// if (packet.
@@ -79,9 +102,9 @@ GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
//}
//
bool
-GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
+GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
Error &error,
- bool &interrupt,
+ bool &interrupt,
bool &quit)
{
StringExtractorGDBRemote packet;
@@ -103,7 +126,7 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
error.SetErrorString("interrupt received");
interrupt = true;
break;
-
+
case StringExtractorGDBRemote::eServerPacketType_unimplemented:
return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
@@ -112,22 +135,25 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
return Handle_qfProcessInfo (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
return Handle_qsProcessInfo (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qC:
return Handle_qC (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
return Handle_qHostInfo (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
return Handle_qLaunchGDBServer (packet);
-
+
+ case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess:
+ return Handle_qKillSpawnedProcess (packet);
+
case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
return Handle_qLaunchSuccess (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qGroupName:
return Handle_qGroupName (packet);
@@ -142,24 +168,60 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
return Handle_QEnvironment (packet);
-
+
+ case StringExtractorGDBRemote::eServerPacketType_QLaunchArch:
+ return Handle_QLaunchArch (packet);
+
case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
return Handle_QSetDisableASLR (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
return Handle_QSetSTDIN (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
return Handle_QSetSTDOUT (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
return Handle_QSetSTDERR (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
return Handle_QSetWorkingDir (packet);
case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
return Handle_QStartNoAckMode (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qPlatform_IO_MkDir:
+ return Handle_qPlatform_IO_MkDir (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qPlatform_RunCommand:
+ return Handle_qPlatform_RunCommand (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Open:
+ return Handle_vFile_Open (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Close:
+ return Handle_vFile_Close (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_pRead:
+ return Handle_vFile_pRead (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_pWrite:
+ return Handle_vFile_pWrite (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Size:
+ return Handle_vFile_Size (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Mode:
+ return Handle_vFile_Mode (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Exists:
+ return Handle_vFile_Exists (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Stat:
+ return Handle_vFile_Stat (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_MD5:
+ return Handle_vFile_MD5 (packet);
}
return true;
}
@@ -207,7 +269,7 @@ bool
GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
{
StreamString response;
-
+
// $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
ArchSpec host_arch (Host::GetArchitecture ());
@@ -222,12 +284,12 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
response.Printf ("cputype:%u;", cpu);
if (sub != LLDB_INVALID_CPUTYPE)
response.Printf ("cpusubtype:%u;", sub);
-
+
if (cpu == ArchSpec::kCore_arm_any)
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;");
-
+
switch (lldb::endian::InlHostByteOrder())
{
case eByteOrderBig: response.PutCString ("endian:big;"); break;
@@ -235,7 +297,7 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
case eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
default: response.PutCString ("endian:unknown;"); break;
}
-
+
uint32_t major = UINT32_MAX;
uint32_t minor = UINT32_MAX;
uint32_t update = UINT32_MAX;
@@ -273,7 +335,7 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
response.PutCStringAsRawHex8(s.c_str());
response.PutChar(';');
}
-
+
return SendPacketNoLock (response.GetData(), response.GetSize()) > 0;
}
@@ -319,7 +381,7 @@ GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &
return SendErrorResponse (1);
}
-bool
+bool
GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
{
m_proc_infos_index = 0;
@@ -329,7 +391,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
packet.SetFilePos(::strlen ("qfProcessInfo"));
if (packet.GetChar() == ':')
{
-
+
std::string key;
std::string value;
while (packet.GetNameColonValue(key, value))
@@ -360,11 +422,11 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
{
match_info.SetNameMatchType (eNameMatchContains);
}
- else if (value.compare("regex") == 0)
+ else if (value.compare("regex") == 0)
{
match_info.SetNameMatchType (eNameMatchRegularExpression);
}
- else
+ else
{
success = false;
}
@@ -405,7 +467,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
{
success = false;
}
-
+
if (!success)
return SendErrorResponse (2);
}
@@ -420,7 +482,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
return SendErrorResponse (3);
}
-bool
+bool
GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
{
if (m_proc_infos_index < m_proc_infos.GetSize())
@@ -433,7 +495,7 @@ GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &pa
return SendErrorResponse (4);
}
-bool
+bool
GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
{
// Packet format: "qUserName:%i" where %i is the uid
@@ -450,10 +512,10 @@ GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet
}
}
return SendErrorResponse (5);
-
+
}
-bool
+bool
GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
{
// Packet format: "qGroupName:%i" where %i is the gid
@@ -539,11 +601,11 @@ AcceptPortFromInferior (void *arg)
// for (int i=0; i<num_retries; i++)
// {
// struct proc_bsdinfo bsd_info;
-// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
-// (uint64_t) 0,
-// &bsd_info,
+// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
+// (uint64_t) 0,
+// &bsd_info,
// PROC_PIDTBSDINFO_SIZE);
-//
+//
// switch (error)
// {
// case EINVAL:
@@ -551,10 +613,10 @@ AcceptPortFromInferior (void *arg)
// case ESRCH:
// case EPERM:
// return false;
-//
+//
// default:
// break;
-//
+//
// case 0:
// if (bsd_info.pbi_status == SSTOP)
// return true;
@@ -567,9 +629,9 @@ AcceptPortFromInferior (void *arg)
bool
GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
{
- // The 'A' packet is the most over designed packet ever here with
- // redundant argument indexes, redundant argument lengths and needed hex
- // encoded argument string values. Really all that is needed is a comma
+ // The 'A' packet is the most over designed packet ever here with
+ // redundant argument indexes, redundant argument lengths and needed hex
+ // encoded argument string values. Really all that is needed is a comma
// separated hex encoded argument value list, but we will stay true to the
// documented version of the 'A' packet here...
@@ -615,7 +677,7 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
if (packet.GetChar() != ',')
success = false;
}
-
+
if (success)
{
if (arg_idx == 0)
@@ -649,11 +711,11 @@ GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
response.Printf("QC%" PRIx64, pid);
if (m_is_platform)
{
- // 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
+ // 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
+ // 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.
@@ -666,8 +728,30 @@ GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
}
bool
+GDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid)
+{
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ return m_spawned_pids.erase(pid) > 0;
+}
+bool
+GDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton,
+ lldb::pid_t pid,
+ bool exited,
+ int signal, // Zero for no signal
+ int status) // Exit value of process if signal is zero
+{
+ GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
+ server->DebugserverProcessReaped (pid);
+ return true;
+}
+
+bool
GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
{
+#ifdef _WIN32
+ // No unix sockets on windows
+ return false;
+#else
// Spawn a local debugserver as a platform so we can then attach or launch
// a process...
@@ -677,49 +761,101 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
ConnectionFileDescriptor file_conn;
char connect_url[PATH_MAX];
Error error;
- char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
- if (::mktemp (unix_socket_name) == NULL)
+ std::string hostname;
+ // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
+ // with the TMPDIR environnement variable
+ char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
+ if (::mkstemp (unix_socket_name) == -1)
{
- error.SetErrorString ("failed to make temporary path for a unix socket");
+ error.SetErrorStringWithFormat("failed to make temporary path for a unix socket: %s", strerror(errno));
}
else
{
+ packet.SetFilePos(::strlen ("qLaunchGDBServer:"));
+ std::string name;
+ std::string value;
+ uint16_t port = UINT16_MAX;
+ while (packet.GetNameColonValue(name, value))
+ {
+ if (name.compare ("host") == 0)
+ hostname.swap(value);
+ else if (name.compare ("port") == 0)
+ port = Args::StringToUInt32(value.c_str(), 0, 0);
+ }
+ if (port == UINT16_MAX)
+ port = GetAndUpdateNextPort();
+
::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
// Spawn a new thread to accept the port that gets bound after
// binding to port 0 (zero).
- lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
- AcceptPortFromInferior,
- connect_url,
- &error);
-
+ lldb::thread_t accept_thread = LLDB_INVALID_HOST_THREAD;
+
+ if (port == 0)
+ {
+ accept_thread = Host::ThreadCreate (unix_socket_name,
+ AcceptPortFromInferior,
+ connect_url,
+ &error);
+ }
+
if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
{
- // Spawn a debugserver and try to get
+ // Spawn a debugserver and try to get the port it listens to.
ProcessLaunchInfo debugserver_launch_info;
- error = StartDebugserverProcess ("localhost:0",
- unix_socket_name,
+ StreamString host_and_port;
+ if (hostname.empty())
+ hostname = "localhost";
+ host_and_port.Printf("%s:%u", hostname.c_str(), port);
+ const char *host_and_port_cstr = host_and_port.GetString().c_str();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr);
+ error = StartDebugserverProcess (host_and_port_cstr,
+ unix_socket_name,
debugserver_launch_info);
-
+
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);
+ }
+ Host::StartMonitoringChildProcess (ReapDebugserverProcess, this, debugserver_pid, false);
+ }
+
if (error.Success())
{
bool success = false;
-
- thread_result_t accept_thread_result = NULL;
- if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
+
+ if (accept_thread)
{
- if (accept_thread_result)
+ thread_result_t accept_thread_result = NULL;
+ if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
{
- uint16_t port = (intptr_t)accept_thread_result;
- char response[256];
- const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
- assert (response_len < (int)sizeof(response));
- //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
- success = SendPacketNoLock (response, response_len) > 0;
+ if (accept_thread_result)
+ {
+ port = (intptr_t)accept_thread_result;
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
+ assert (response_len < sizeof(response));
+ //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+ success = SendPacketNoLock (response, response_len) > 0;
+ }
}
}
+ else
+ {
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
+ assert (response_len < sizeof(response));
+ //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+ success = SendPacketNoLock (response, response_len) > 0;
+
+ }
::unlink (unix_socket_name);
-
+
if (!success)
{
if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
@@ -730,7 +866,61 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
}
}
}
- return SendErrorResponse (13);
+ return SendErrorResponse (9);
+#endif
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
+{
+ // Spawn a local debugserver as a platform so we can then attach or launch
+ // a process...
+
+ if (m_is_platform)
+ {
+ packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
+
+ lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
+
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return SendErrorResponse (10);
+ }
+ Host::Kill (pid, SIGTERM);
+
+ for (size_t i=0; i<10; ++i)
+ {
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+ usleep (10000);
+ }
+
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+ Host::Kill (pid, SIGKILL);
+
+ for (size_t i=0; i<10; ++i)
+ {
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+ usleep (10000);
+ }
+ }
+ return SendErrorResponse (10);
}
bool
@@ -738,7 +928,7 @@ GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &p
{
if (m_process_launch_error.Success())
return SendOKResponse();
- StreamString response;
+ StreamString response;
response.PutChar('E');
response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
return SendPacketNoLock (response.GetData(), response.GetSize());
@@ -754,7 +944,22 @@ GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &pa
m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
return SendOKResponse ();
}
- return SendErrorResponse (9);
+ return SendErrorResponse (11);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("QLaunchArch:"));
+ const uint32_t bytes_left = packet.GetBytesLeft();
+ if (bytes_left > 0)
+ {
+ const char* arch_triple = packet.Peek();
+ ArchSpec arch_spec(arch_triple,NULL);
+ m_process_launch_info.SetArchitecture(arch_spec);
+ return SendOKResponse();
+ }
+ return SendErrorResponse(12);
}
bool
@@ -792,7 +997,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (10);
+ return SendErrorResponse (13);
}
bool
@@ -809,7 +1014,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packe
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (11);
+ return SendErrorResponse (14);
}
bool
@@ -826,7 +1031,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packe
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (12);
+ return SendErrorResponse (15);
}
bool
@@ -837,3 +1042,277 @@ GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &
m_send_acks = false;
return true;
}
+
+bool
+GDBRemoteCommunicationServer::Handle_qPlatform_IO_MkDir (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("qPlatform_IO_MkDir:"));
+ mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ std::string path;
+ packet.GetHexByteString(path);
+ uint32_t retcode = Host::MakeDirectory(path.c_str(),mode);
+ StreamString response;
+ response.PutHex32(retcode);
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:open:"));
+ std::string path;
+ packet.GetHexByteStringTerminatedBy(path,',');
+ if (path.size() == 0)
+ return false;
+ if (packet.GetChar() != ',')
+ return false;
+ uint32_t flags = packet.GetHexMaxU32(false, UINT32_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
+ Error error;
+ int fd = ::open (path.c_str(), flags, mode);
+ const int save_errno = fd == -1 ? errno : 0;
+ StreamString response;
+ response.PutChar('F');
+ response.Printf("%i", fd);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:close:"));
+ int fd = packet.GetS32(-1);
+ Error error;
+ int err = -1;
+ int save_errno = 0;
+ if (fd >= 0)
+ {
+ err = close(fd);
+ save_errno = err == -1 ? errno : 0;
+ }
+ else
+ {
+ save_errno = EINVAL;
+ }
+ StreamString response;
+ response.PutChar('F');
+ response.Printf("%i", err);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet)
+{
+#ifdef _WIN32
+ // Not implemented on Windows
+ return false;
+#else
+ StreamGDBRemote response;
+ packet.SetFilePos(::strlen("vFile:pread:"));
+ int fd = packet.GetS32(-1);
+ if (packet.GetChar() != ',')
+ return false;
+ uint64_t count = packet.GetU64(UINT64_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ uint64_t offset = packet.GetU64(UINT32_MAX);
+ if (count == UINT64_MAX)
+ {
+ response.Printf("F-1:%i", EINVAL);
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+ }
+ std::string buffer(count, 0);
+ const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
+ const int save_errno = bytes_read == -1 ? errno : 0;
+ response.PutChar('F');
+ response.Printf("%zi", bytes_read);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ else
+ {
+ response.PutChar(';');
+ response.PutEscapedBytes(&buffer[0], bytes_read);
+ }
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+#endif
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
+{
+#ifdef _WIN32
+ // Not implemented on Windows
+ return false;
+#else
+ packet.SetFilePos(::strlen("vFile:pwrite:"));
+
+ StreamGDBRemote response;
+ response.PutChar('F');
+
+ int fd = packet.GetU32(UINT32_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ off_t offset = packet.GetU64(UINT32_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ std::string buffer;
+ if (packet.GetEscapedBinaryData(buffer))
+ {
+ const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
+ const int save_errno = bytes_written == -1 ? errno : 0;
+ response.Printf("%zi", bytes_written);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ }
+ else
+ {
+ response.Printf ("-1,%i", EINVAL);
+ }
+
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+#endif
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:size:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.empty())
+ return false;
+ lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
+ StreamString response;
+ response.PutChar('F');
+ response.PutHex64(retcode);
+ if (retcode == UINT64_MAX)
+ {
+ response.PutChar(',');
+ response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
+ }
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:mode:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.empty())
+ return false;
+ Error error;
+ const uint32_t mode = File::GetPermissions(path.c_str(), error);
+ StreamString response;
+ response.Printf("F%u", mode);
+ if (mode == 0 || error.Fail())
+ response.Printf(",%i", (int)error.GetError());
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:exists:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.empty())
+ return false;
+ bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
+ StreamString response;
+ response.PutChar('F');
+ response.PutChar(',');
+ if (retcode)
+ response.PutChar('1');
+ else
+ response.PutChar('0');
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qPlatform_RunCommand (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("qPlatform_RunCommand:"));
+ std::string path;
+ std::string working_dir;
+ packet.GetHexByteStringTerminatedBy(path,',');
+ if (path.size() == 0)
+ return false;
+ if (packet.GetChar() != ',')
+ return false;
+ // FIXME: add timeout to qPlatform_RunCommand packet
+ // uint32_t timeout = packet.GetHexMaxU32(false, 32);
+ uint32_t timeout = 10;
+ if (packet.GetChar() == ',')
+ packet.GetHexByteString(working_dir);
+ int status, signo;
+ std::string output;
+ Error err = Host::RunShellCommand(path.c_str(),
+ working_dir.empty() ? NULL : working_dir.c_str(),
+ &status, &signo, &output, timeout);
+ StreamGDBRemote response;
+ if (err.Fail())
+ {
+ response.PutCString("F,");
+ response.PutHex32(UINT32_MAX);
+ }
+ else
+ {
+ response.PutCString("F,");
+ response.PutHex32(status);
+ response.PutChar(',');
+ response.PutHex32(signo);
+ response.PutChar(',');
+ response.PutEscapedBytes(output.c_str(), output.size());
+ }
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
+{
+ return false;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:exists:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.size() == 0)
+ return false;
+ uint64_t a,b;
+ StreamGDBRemote response;
+ if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false)
+ {
+ response.PutCString("F,");
+ response.PutCString("x");
+ }
+ else
+ {
+ response.PutCString("F,");
+ response.PutHex64(a);
+ response.PutHex64(b);
+ }
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index cce0e4e64c1e..64f6f8de1a21 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -12,10 +12,12 @@
// C Includes
// C++ Includes
+#include <vector>
+#include <set>
// Other libraries and framework includes
// Project includes
+#include "lldb/Host/Mutex.h"
#include "lldb/Target/Process.h"
-
#include "GDBRemoteCommunication.h"
class ProcessGDBRemote;
@@ -60,6 +62,21 @@ public:
{
m_lo_port_num = lo_port_num;
m_hi_port_num = hi_port_num;
+ m_next_port = m_lo_port_num;
+ m_use_port_range = true;
+ }
+
+ // If we are using a port range, get and update the next port to be used variable.
+ // Otherwise, just return 0.
+ uint16_t
+ GetAndUpdateNextPort ()
+ {
+ if (!m_use_port_range)
+ return 0;
+ uint16_t val = m_next_port;
+ if (++m_next_port > m_hi_port_num)
+ m_next_port = m_lo_port_num;
+ return val;
}
protected:
@@ -68,11 +85,16 @@ protected:
lldb::thread_t m_async_thread;
lldb_private::ProcessLaunchInfo m_process_launch_info;
lldb_private::Error m_process_launch_error;
+ std::set<lldb::pid_t> m_spawned_pids;
+ lldb_private::Mutex m_spawned_pids_mutex;
lldb_private::ProcessInstanceInfoList m_proc_infos;
uint32_t m_proc_infos_index;
uint16_t m_lo_port_num;
uint16_t m_hi_port_num;
//PortToPIDMap m_port_to_pid_map;
+ uint16_t m_next_port;
+ bool m_use_port_range;
+
size_t
SendUnimplementedResponse (const char *packet);
@@ -85,7 +107,7 @@ protected:
bool
Handle_A (StringExtractorGDBRemote &packet);
-
+
bool
Handle_qLaunchSuccess (StringExtractorGDBRemote &packet);
@@ -94,8 +116,14 @@ protected:
bool
Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
bool
+ Handle_qPlatform_IO_MkDir (StringExtractorGDBRemote &packet);
+
+ bool
Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
bool
@@ -120,6 +148,9 @@ protected:
Handle_QEnvironment (StringExtractorGDBRemote &packet);
bool
+ Handle_QLaunchArch (StringExtractorGDBRemote &packet);
+
+ bool
Handle_QSetDisableASLR (StringExtractorGDBRemote &packet);
bool
@@ -137,7 +168,47 @@ protected:
bool
Handle_QSetSTDERR (StringExtractorGDBRemote &packet);
+ bool
+ Handle_vFile_Open (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Close (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_pRead (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_pWrite (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Size (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Mode (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Exists (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Stat (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_MD5 (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_qPlatform_RunCommand (StringExtractorGDBRemote &packet);
+
private:
+ bool
+ DebugserverProcessReaped (lldb::pid_t pid);
+
+ static bool
+ ReapDebugserverProcess (void *callback_baton,
+ lldb::pid_t pid,
+ bool exited,
+ int signal,
+ int status);
+
//------------------------------------------------------------------
// For GDBRemoteCommunicationServer only
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index b1612a5f3c2f..c4e468f89f35 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -17,6 +17,9 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
+#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Interpreter/PythonDataObjects.h"
+#endif
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/Utils.h"
// Project includes
@@ -54,7 +57,7 @@ GDBRemoteRegisterContext::GDBRemoteRegisterContext
// Make a heap based buffer that is big enough to store all registers
DataBufferSP reg_data_sp(new DataBufferHeap (reg_info.GetRegisterDataByteSize(), 0));
m_reg_data.SetData (reg_data_sp);
-
+ m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder());
}
//----------------------------------------------------------------------
@@ -696,6 +699,7 @@ GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, ui
return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num);
}
+
void
GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch)
{
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 3110ddf8edf9..7a49d693d44e 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -21,23 +21,20 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Target/RegisterContext.h"
+#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
+
#include "GDBRemoteCommunicationClient.h"
class ThreadGDBRemote;
class ProcessGDBRemote;
class StringExtractor;
-class GDBRemoteDynamicRegisterInfo
+class GDBRemoteDynamicRegisterInfo :
+ public DynamicRegisterInfo
{
public:
GDBRemoteDynamicRegisterInfo () :
- m_regs (),
- m_sets (),
- m_set_reg_nums (),
- m_reg_names (),
- m_reg_alt_names (),
- m_set_names (),
- m_reg_data_byte_size (0)
+ DynamicRegisterInfo()
{
}
@@ -46,151 +43,8 @@ public:
}
void
- AddRegister (lldb_private::RegisterInfo reg_info,
- lldb_private::ConstString &reg_name,
- lldb_private::ConstString &reg_alt_name,
- lldb_private::ConstString &set_name)
- {
- const uint32_t reg_num = (uint32_t)m_regs.size();
- m_reg_names.push_back (reg_name);
- m_reg_alt_names.push_back (reg_alt_name);
- reg_info.name = reg_name.AsCString();
- assert (reg_info.name);
- reg_info.alt_name = reg_alt_name.AsCString(NULL);
- uint32_t i;
- if (reg_info.value_regs)
- {
- for (i=0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i)
- m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]);
- m_value_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
- reg_info.value_regs = m_value_regs_map[reg_num].data();
- }
- if (reg_info.invalidate_regs)
- {
- for (i=0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i)
- m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]);
- m_invalidate_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
- reg_info.invalidate_regs = m_invalidate_regs_map[reg_num].data();
- }
- m_regs.push_back (reg_info);
- uint32_t set = GetRegisterSetIndexByName (set_name);
- assert (set < m_sets.size());
- assert (set < m_set_reg_nums.size());
- assert (set < m_set_names.size());
- m_set_reg_nums[set].push_back(reg_num);
- size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
- if (m_reg_data_byte_size < end_reg_offset)
- m_reg_data_byte_size = end_reg_offset;
- }
-
- void
- Finalize ()
- {
- for (uint32_t set = 0; set < m_sets.size(); ++set)
- {
- assert (m_sets.size() == m_set_reg_nums.size());
- m_sets[set].num_registers = m_set_reg_nums[set].size();
- m_sets[set].registers = &m_set_reg_nums[set][0];
- }
- }
-
- size_t
- GetNumRegisters() const
- {
- return m_regs.size();
- }
-
- size_t
- GetNumRegisterSets() const
- {
- return m_sets.size();
- }
-
- size_t
- GetRegisterDataByteSize() const
- {
- return m_reg_data_byte_size;
- }
-
- const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (uint32_t i) const
- {
- if (i < m_regs.size())
- return &m_regs[i];
- return NULL;
- }
-
- const lldb_private::RegisterSet *
- GetRegisterSet (uint32_t i) const
- {
- if (i < m_sets.size())
- return &m_sets[i];
- return NULL;
- }
-
- uint32_t
- GetRegisterSetIndexByName (lldb_private::ConstString &set_name)
- {
- name_collection::iterator pos, end = m_set_names.end();
- for (pos = m_set_names.begin(); pos != end; ++pos)
- {
- if (*pos == set_name)
- return static_cast<uint32_t>(std::distance (m_set_names.begin(), pos));
- }
-
- m_set_names.push_back(set_name);
- m_set_reg_nums.resize(m_set_reg_nums.size()+1);
- lldb_private::RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
- m_sets.push_back (new_set);
- return static_cast<uint32_t>(m_sets.size() - 1);
- }
-
- uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const
- {
- reg_collection::const_iterator pos, end = m_regs.end();
- for (pos = m_regs.begin(); pos != end; ++pos)
- {
- if (pos->kinds[kind] == num)
- return static_cast<uint32_t>(std::distance (m_regs.begin(), pos));
- }
-
- return LLDB_INVALID_REGNUM;
- }
- void
- Clear()
- {
- m_regs.clear();
- m_sets.clear();
- m_set_reg_nums.clear();
- m_reg_names.clear();
- m_reg_alt_names.clear();
- m_set_names.clear();
- }
-
- void
HardcodeARMRegisters(bool from_scratch);
-protected:
- //------------------------------------------------------------------
- // Classes that inherit from GDBRemoteRegisterContext can see and modify these
- //------------------------------------------------------------------
- typedef std::vector <lldb_private::RegisterInfo> reg_collection;
- typedef std::vector <lldb_private::RegisterSet> set_collection;
- typedef std::vector <uint32_t> reg_num_collection;
- typedef std::vector <reg_num_collection> set_reg_num_collection;
- typedef std::vector <lldb_private::ConstString> name_collection;
- typedef std::map<uint32_t, reg_num_collection> reg_to_regs_map;
-
- reg_collection m_regs;
- set_collection m_sets;
- set_reg_num_collection m_set_reg_nums;
- name_collection m_reg_names;
- name_collection m_reg_alt_names;
- name_collection m_set_names;
- reg_to_regs_map m_value_regs_map;
- reg_to_regs_map m_invalidate_regs_map;
- size_t m_reg_data_byte_size; // The number of bytes required to store all registers
};
class GDBRemoteRegisterContext : public lldb_private::RegisterContext
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index d27207f121d3..aff9c7bc977c 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -8,13 +8,16 @@
//===----------------------------------------------------------------------===//
#include "lldb/lldb-python.h"
+#include "lldb/Host/Config.h"
// C Includes
#include <errno.h>
-#include <spawn.h>
#include <stdlib.h>
+#ifndef LLDB_DISABLE_POSIX
+#include <spawn.h>
#include <netinet/in.h>
#include <sys/mman.h> // for mmap
+#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
@@ -46,6 +49,9 @@
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Interpreter/PythonDataObjects.h"
+#endif
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Target.h"
@@ -94,12 +100,14 @@ namespace {
g_properties[] =
{
{ "packet-timeout" , OptionValue::eTypeUInt64 , true , 1, NULL, NULL, "Specify the default packet timeout in seconds." },
+ { "target-definition-file" , OptionValue::eTypeFileSpec , true, 0 , NULL, NULL, "The file that provides the description for remote target registers." },
{ NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL }
};
enum
{
- ePropertyPacketTimeout
+ ePropertyPacketTimeout,
+ ePropertyTargetDefinitionFile
};
class PluginProperties : public Properties
@@ -130,6 +138,20 @@ namespace {
const uint32_t idx = ePropertyPacketTimeout;
return m_collection_sp->GetPropertyAtIndexAsUInt64(NULL, idx, g_properties[idx].default_uint_value);
}
+
+ bool
+ SetPacketTimeout(uint64_t timeout)
+ {
+ const uint32_t idx = ePropertyPacketTimeout;
+ return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout);
+ }
+
+ FileSpec
+ GetTargetDefinitionFile () const
+ {
+ const uint32_t idx = ePropertyTargetDefinitionFile;
+ return m_collection_sp->GetPropertyAtIndexAsFileSpec (NULL, idx);
+ }
};
typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
@@ -254,13 +276,13 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
m_continue_C_tids (),
m_continue_s_tids (),
m_continue_S_tids (),
- m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS),
m_max_memory_size (512),
m_addr_to_mmap_size (),
m_thread_create_bp_sp (),
m_waiting_for_attach (false),
m_destroy_tried_resuming (false),
- m_command_sp ()
+ m_command_sp (),
+ m_breakpoint_pc_offset (0)
{
m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue");
@@ -305,6 +327,48 @@ ProcessGDBRemote::GetPluginVersion()
return 1;
}
+bool
+ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_fspec)
+{
+#ifndef LLDB_DISABLE_PYTHON
+ ScriptInterpreter *interpreter = GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ Error error;
+ lldb::ScriptInterpreterObjectSP module_object_sp (interpreter->LoadPluginModule(target_definition_fspec, error));
+ if (module_object_sp)
+ {
+ lldb::ScriptInterpreterObjectSP target_definition_sp (interpreter->GetDynamicSettings(module_object_sp,
+ &GetTarget(),
+ "gdb-server-target-definition",
+ error));
+
+ PythonDictionary target_dict(target_definition_sp);
+
+ if (target_dict)
+ {
+ PythonDictionary host_info_dict (target_dict.GetItemForKey("host-info"));
+ if (host_info_dict)
+ {
+ ArchSpec host_arch (host_info_dict.GetItemForKeyAsString(PythonString("triple")));
+
+ if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture()))
+ {
+ GetTarget().SetArchitecture(host_arch);
+ }
+
+ }
+ m_breakpoint_pc_offset = target_dict.GetItemForKeyAsInteger("breakpoint-pc-offset", 0);
+
+ if (m_register_info.SetRegisterInfo (target_dict, GetTarget().GetArchitecture().GetByteOrder()) > 0)
+ {
+ return true;
+ }
+ }
+ }
+#endif
+ return false;
+}
+
+
void
ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
{
@@ -480,6 +544,28 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
}
}
+ // Check if qHostInfo specified a specific packet timeout for this connection.
+ // If so then lets update our setting so the user knows what the timeout is
+ // and can see it.
+ const uint32_t host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout();
+ if (host_packet_timeout)
+ {
+ GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout);
+ }
+
+
+ if (reg_num == 0)
+ {
+ FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile ();
+
+ if (target_definition_fspec)
+ {
+ // See if we can get register definitions from a python file
+ if (ParsePythonTargetDefinition (target_definition_fspec))
+ return;
+ }
+ }
+
// We didn't get anything if the accumulated reg_num is zero. See if we are
// debugging ARM and fill with a hard coded register set until we can get an
// updated debugserver down on the devices.
@@ -561,6 +647,11 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
GetThreadList();
if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
{
+ if (!m_target.GetArchitecture().IsValid()) { // Make sure we have an architecture
+ m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ }
+
+
const StateType state = SetThreadStopInfo (m_last_stop_packet);
if (state == eStateStopped)
{
@@ -759,6 +850,10 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, const ProcessLaunchInfo &launch_
if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
{
+ if (!m_target.GetArchitecture().IsValid()) { // Make sure we have an architecture
+ m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ }
+
SetPrivateState (SetThreadStopInfo (m_last_stop_packet));
if (!disable_stdio)
@@ -863,8 +958,6 @@ ProcessGDBRemote::DidLaunchOrAttach ()
log->Printf ("ProcessGDBRemote::DidLaunch()");
if (GetID() != LLDB_INVALID_PROCESS_ID)
{
- m_dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS;
-
BuildDynamicRegisterInfo (false);
// See if the GDB server supports the qHostInfo information
@@ -1654,7 +1747,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
// Currently we are going to assume SIGTRAP means we are either
// hitting a breakpoint or hardware single stepping.
handled = true;
- addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ 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)
@@ -1664,6 +1757,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
// will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
if (bp_site_sp->ValidForThisThread (thread_sp.get()))
{
+ if(m_breakpoint_pc_offset != 0)
+ thread_sp->GetRegisterContext()->SetPC(pc);
thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
}
else
@@ -2220,7 +2315,7 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site)
{
const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
- if (bp_site->HardwarePreferred())
+ if (bp_site->HardwareRequired())
{
// Try and set hardware breakpoint, and if that fails, fall through
// and set a software breakpoint?
@@ -2230,12 +2325,19 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site)
{
bp_site->SetEnabled(true);
bp_site->SetType (BreakpointSite::eHardware);
- return error;
}
+ else
+ {
+ error.SetErrorString("failed to set hardware breakpoint (hardware breakpoint resources might be exhausted or unavailable)");
+ }
+ }
+ else
+ {
+ error.SetErrorString("hardware breakpoints are not supported");
}
+ return error;
}
-
- if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
+ else if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
{
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
{
@@ -2687,7 +2789,7 @@ ProcessGDBRemote::KillDebugserverProcess ()
{
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
{
- ::kill (m_debugserver_pid, SIGINT);
+ Host::Kill (m_debugserver_pid, SIGINT);
m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
}
}
@@ -2794,7 +2896,7 @@ ProcessGDBRemote::StopAsyncThread ()
}
-void *
+thread_result_t
ProcessGDBRemote::AsyncThread (void *arg)
{
ProcessGDBRemote *process = (ProcessGDBRemote*) arg;
@@ -2916,97 +3018,6 @@ ProcessGDBRemote::AsyncThread (void *arg)
return NULL;
}
-const char *
-ProcessGDBRemote::GetDispatchQueueNameForThread
-(
- addr_t thread_dispatch_qaddr,
- std::string &dispatch_queue_name
-)
-{
- dispatch_queue_name.clear();
- if (thread_dispatch_qaddr != 0 && thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
- {
- // Cache the dispatch_queue_offsets_addr value so we don't always have
- // to look it up
- if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
- {
- static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets");
- const Symbol *dispatch_queue_offsets_symbol = NULL;
- ModuleSpec libSystem_module_spec (FileSpec("libSystem.B.dylib", false));
- ModuleSP module_sp(GetTarget().GetImages().FindFirstModule (libSystem_module_spec));
- if (module_sp)
- dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
-
- if (dispatch_queue_offsets_symbol == NULL)
- {
- ModuleSpec libdispatch_module_spec (FileSpec("libdispatch.dylib", false));
- module_sp = GetTarget().GetImages().FindFirstModule (libdispatch_module_spec);
- if (module_sp)
- dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
- }
- if (dispatch_queue_offsets_symbol)
- m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetAddress().GetLoadAddress(&m_target);
-
- if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
- return NULL;
- }
-
- uint8_t memory_buffer[8];
- DataExtractor data (memory_buffer,
- sizeof(memory_buffer),
- m_target.GetArchitecture().GetByteOrder(),
- m_target.GetArchitecture().GetAddressByteSize());
-
- // Excerpt from src/queue_private.h
- struct dispatch_queue_offsets_s
- {
- uint16_t dqo_version;
- uint16_t dqo_label; // in version 1-3, offset to string; in version 4+, offset to a pointer to a string
- uint16_t dqo_label_size; // in version 1-3, length of string; in version 4+, size of a (void*) in this process
- } dispatch_queue_offsets;
-
-
- Error error;
- if (ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets), error) == sizeof(dispatch_queue_offsets))
- {
- lldb::offset_t data_offset = 0;
- if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t)))
- {
- if (ReadMemory (thread_dispatch_qaddr, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
- {
- data_offset = 0;
- lldb::addr_t queue_addr = data.GetAddress(&data_offset);
- if (dispatch_queue_offsets.dqo_version >= 4)
- {
- // libdispatch versions 4+, pointer to dispatch name is in the
- // queue structure.
- lldb::addr_t pointer_to_label_address = queue_addr + dispatch_queue_offsets.dqo_label;
- if (ReadMemory (pointer_to_label_address, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
- {
- data_offset = 0;
- lldb::addr_t label_addr = data.GetAddress(&data_offset);
- ReadCStringFromMemory (label_addr, dispatch_queue_name, error);
- }
- }
- else
- {
- // libdispatch versions 1-3, dispatch name is a fixed width char array
- // in the queue structure.
- lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label;
- dispatch_queue_name.resize(dispatch_queue_offsets.dqo_label_size, '\0');
- size_t bytes_read = ReadMemory (label_addr, &dispatch_queue_name[0], dispatch_queue_offsets.dqo_label_size, error);
- if (bytes_read < dispatch_queue_offsets.dqo_label_size)
- dispatch_queue_name.erase (bytes_read);
- }
- }
- }
- }
- }
- if (dispatch_queue_name.empty())
- return NULL;
- return dispatch_queue_name.c_str();
-}
-
//uint32_t
//ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
//{
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index e104b7191eab..b18ac5b1723e 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -291,6 +291,12 @@ protected:
void
SetLastStopPacket (const StringExtractorGDBRemote &response);
+ bool
+ ParsePythonTargetDefinition(const lldb_private::FileSpec &target_definition_fspec);
+
+ bool
+ ParseRegisters(lldb_private::ScriptInterpreterObject *registers_array);
+
//------------------------------------------------------------------
/// Broadcaster event bits definitions.
//------------------------------------------------------------------
@@ -326,13 +332,13 @@ 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
- lldb::addr_t m_dispatch_queue_offsets_addr;
size_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
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 ();
@@ -340,7 +346,7 @@ protected:
void
StopAsyncThread ();
- static void *
+ static lldb::thread_result_t
AsyncThread (void *arg);
static bool
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 38fb84d66ef3..4e475c80bdab 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -10,16 +10,17 @@
#include "ThreadGDBRemote.h"
+#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/StreamString.h"
#include "lldb/Core/State.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Unwind.h"
-#include "lldb/Breakpoint/Watchpoint.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
@@ -73,13 +74,38 @@ ThreadGDBRemote::GetQueueName ()
ProcessSP process_sp (GetProcess());
if (process_sp)
{
- ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
- return gdb_process->GetDispatchQueueNameForThread (m_thread_dispatch_qaddr, m_dispatch_queue_name);
+ PlatformSP platform_sp (process_sp->GetTarget().GetPlatform());
+ if (platform_sp)
+ {
+ m_dispatch_queue_name = platform_sp->GetQueueNameForThreadQAddress (process_sp.get(), m_thread_dispatch_qaddr);
+ }
+ if (m_dispatch_queue_name.length() > 0)
+ {
+ return m_dispatch_queue_name.c_str();
+ }
}
}
return NULL;
}
+queue_id_t
+ThreadGDBRemote::GetQueueID ()
+{
+ if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+ {
+ ProcessSP process_sp (GetProcess());
+ if (process_sp)
+ {
+ PlatformSP platform_sp (process_sp->GetTarget().GetPlatform());
+ if (platform_sp)
+ {
+ return platform_sp->GetQueueIDForThreadQAddress (process_sp.get(), m_thread_dispatch_qaddr);
+ }
+ }
+ }
+ return LLDB_INVALID_QUEUE_ID;
+}
+
void
ThreadGDBRemote::WillResume (StateType resume_state)
{
@@ -164,7 +190,6 @@ lldb::RegisterContextSP
ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
{
lldb::RegisterContextSP reg_ctx_sp;
- const bool read_all_registers_at_once = false;
uint32_t concrete_frame_idx = 0;
if (frame)
@@ -177,6 +202,8 @@ ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
if (process_sp)
{
ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
+ // read_all_registers_at_once will be true if 'p' packet is not supported.
+ bool read_all_registers_at_once = !gdb_process->GetGDBRemote().GetpPacketSupported (GetID());
reg_ctx_sp.reset (new GDBRemoteRegisterContext (*this, concrete_frame_idx, gdb_process->m_register_info, read_all_registers_at_once));
}
}
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index 50a3f19c6505..dd4cc036ef8b 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -38,6 +38,9 @@ public:
virtual const char *
GetQueueName ();
+ virtual lldb::queue_id_t
+ GetQueueID ();
+
virtual lldb::RegisterContextSP
GetRegisterContext ();
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
index 06e87eab33ce..ff2e3762556a 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -32,13 +32,13 @@ DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration(dw_tag_t tag, uint8_t
}
bool
-DWARFAbbreviationDeclaration::Extract(const DataExtractor& data, lldb::offset_t* offset_ptr)
+DWARFAbbreviationDeclaration::Extract(const DWARFDataExtractor& data, lldb::offset_t* offset_ptr)
{
return Extract(data, offset_ptr, data.GetULEB128(offset_ptr));
}
bool
-DWARFAbbreviationDeclaration::Extract(const DataExtractor& data, lldb::offset_t *offset_ptr, dw_uleb128_t code)
+DWARFAbbreviationDeclaration::Extract(const DWARFDataExtractor& data, lldb::offset_t *offset_ptr, dw_uleb128_t code)
{
m_code = code;
m_attributes.clear();
@@ -139,7 +139,7 @@ DWARFAbbreviationDeclaration::CopyExcludingAddressAttributes(const DWARFAbbrevia
void
DWARFAbbreviationDeclaration::CopyChangingStringToStrp(
const DWARFAbbreviationDeclaration& abbr_decl,
- const DataExtractor& debug_info_data,
+ const DWARFDataExtractor& debug_info_data,
dw_offset_t debug_info_offset,
const DWARFCompileUnit* cu,
const uint32_t strp_min_len
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
index f462b7fc108d..48b9ebe37ee7 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
@@ -58,13 +58,13 @@ public:
void CopyExcludingAddressAttributes(const DWARFAbbreviationDeclaration& abbr_decl, const uint32_t idx);
void CopyChangingStringToStrp(
const DWARFAbbreviationDeclaration& abbr_decl,
- const lldb_private::DataExtractor& debug_info_data,
+ 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::DataExtractor& data, lldb::offset_t *offset_ptr);
- bool Extract(const lldb_private::DataExtractor& data, lldb::offset_t *offset_ptr, dw_uleb128_t code);
+ 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;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
index 8310b1dda5f1..40c8af3d6e8e 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
@@ -28,7 +28,7 @@ public:
dw_form_t get_form() const { return (dw_form_t)m_attr_form; }
void get(dw_attr_t& attr, dw_form_t& form) const
{
- register uint32_t attr_form = m_attr_form;
+ uint32_t attr_form = m_attr_form;
attr = attr_form >> 16;
form = (dw_form_t)attr_form;
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index 493b3af6ecd1..cf664db28acd 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -69,7 +69,7 @@ DWARFCompileUnit::Clear()
}
bool
-DWARFCompileUnit::Extract(const DataExtractor &debug_info, lldb::offset_t *offset_ptr)
+DWARFCompileUnit::Extract(const DWARFDataExtractor &debug_info, lldb::offset_t *offset_ptr)
{
Clear();
@@ -103,30 +103,6 @@ DWARFCompileUnit::Extract(const DataExtractor &debug_info, lldb::offset_t *offse
}
-dw_offset_t
-DWARFCompileUnit::Extract(lldb::offset_t offset, const DataExtractor& debug_info_data, const DWARFAbbreviationDeclarationSet* abbrevs)
-{
- Clear();
-
- m_offset = offset;
-
- if (debug_info_data.ValidOffset(offset))
- {
- m_length = debug_info_data.GetU32(&offset);
- m_version = debug_info_data.GetU16(&offset);
- bool abbrevs_OK = debug_info_data.GetU32(&offset) == abbrevs->GetOffset();
- m_abbrevs = abbrevs;
- m_addr_size = debug_info_data.GetU8 (&offset);
-
- bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
- bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
-
- if (version_OK && addr_size_OK && abbrevs_OK && debug_info_data.ValidOffset(offset))
- return offset;
- }
- return DW_INVALID_OFFSET;
-}
-
void
DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die)
{
@@ -187,7 +163,7 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
uint32_t depth = 0;
// We are in our compile unit, parse starting at the offset
// we were told to parse
- const DataExtractor& debug_info_data = m_dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor& debug_info_data = m_dwarf2Data->get_debug_info_data();
std::vector<uint32_t> die_index_stack;
die_index_stack.reserve(32);
die_index_stack.push_back(0);
@@ -312,7 +288,7 @@ DWARFCompileUnit::GetAbbrevOffset() const
bool
DWARFCompileUnit::Verify(Stream *s) const
{
- const DataExtractor& debug_info = m_dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor& debug_info = m_dwarf2Data->get_debug_info_data();
bool valid_offset = debug_info.ValidOffset(m_offset);
bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1);
bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
@@ -612,7 +588,7 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
NameToDIE& types,
NameToDIE& namespaces)
{
- const DataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data();
+ const DWARFDataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data();
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize());
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
index 9fee0a2d2236..35597f389423 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -29,8 +29,7 @@ public:
DWARFCompileUnit(SymbolFileDWARF* dwarf2Data);
- bool Extract(const lldb_private::DataExtractor &debug_info, lldb::offset_t *offset_ptr);
- dw_offset_t Extract(lldb::offset_t offset, const lldb_private::DataExtractor& debug_info_data, const DWARFAbbreviationDeclarationSet* abbrevs);
+ bool Extract(const lldb_private::DWARFDataExtractor &debug_info, lldb::offset_t *offset_ptr);
size_t ExtractDIEsIfNeeded (bool cu_die_only);
bool LookupAddress(
const dw_addr_t address,
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
new file mode 100644
index 000000000000..9bf47cd7a9ac
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
@@ -0,0 +1,30 @@
+//===-- DWARFDataExtractor.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDataExtractor.h"
+
+namespace lldb_private {
+
+uint64_t
+DWARFDataExtractor::GetDWARFInitialLength(lldb::offset_t *offset_ptr) const
+{
+ uint64_t length = GetU32(offset_ptr);
+ m_is_dwarf64 = (length == UINT32_MAX);
+ if (m_is_dwarf64)
+ length = GetU64(offset_ptr);
+ return length;
+}
+
+dw_offset_t
+DWARFDataExtractor::GetDWARFOffset(lldb::offset_t *offset_ptr) const
+{
+ return GetMaxU64(offset_ptr, m_is_dwarf64 ? 8 : 4);
+}
+
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
new file mode 100644
index 000000000000..6e5b974a71ff
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
@@ -0,0 +1,43 @@
+//===-- DWARFDataExtractor.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_DWARFDataExtractor_h_
+#define liblldb_DWARFDataExtractor_h_
+
+// Other libraries and framework includes.
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/dwarf.h"
+
+namespace lldb_private {
+
+class DWARFDataExtractor : public lldb_private::DataExtractor
+{
+public:
+ DWARFDataExtractor() : DataExtractor(), m_is_dwarf64(false) { };
+
+ DWARFDataExtractor (const DWARFDataExtractor& data, lldb::offset_t offset, lldb::offset_t length) :
+ DataExtractor(data, offset, length), m_is_dwarf64(false) { };
+
+ uint64_t
+ GetDWARFInitialLength(lldb::offset_t *offset_ptr) const;
+
+ dw_offset_t
+ GetDWARFOffset(lldb::offset_t *offset_ptr) const;
+
+ size_t
+ GetDWARFSizeofInitialLength() const { return m_is_dwarf64 ? 12 : 4; }
+
+protected:
+ mutable bool m_is_dwarf64;
+};
+
+}
+
+#endif // liblldb_DWARFDataExtractor_h_
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
index 47657d5089b2..6773d0762a21 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#include "DWARFDebugAbbrev.h"
-#include "lldb/Core/DataExtractor.h"
+#include "DWARFDataExtractor.h"
#include "lldb/Core/Stream.h"
using namespace lldb;
@@ -30,7 +30,7 @@ DWARFAbbreviationDeclarationSet::Clear()
// DWARFAbbreviationDeclarationSet::Extract()
//----------------------------------------------------------------------
bool
-DWARFAbbreviationDeclarationSet::Extract(const DataExtractor& data, lldb::offset_t *offset_ptr)
+DWARFAbbreviationDeclarationSet::Extract(const DWARFDataExtractor& data, lldb::offset_t *offset_ptr)
{
const lldb::offset_t begin_offset = *offset_ptr;
m_offset = begin_offset;
@@ -142,7 +142,7 @@ DWARFDebugAbbrev::DWARFDebugAbbrev() :
// DWARFDebugAbbrev::Parse()
//----------------------------------------------------------------------
void
-DWARFDebugAbbrev::Parse(const DataExtractor& data)
+DWARFDebugAbbrev::Parse(const DWARFDataExtractor& data)
{
lldb::offset_t offset = 0;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
index eba439928a2c..8ec2c4ba8e21 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
@@ -43,7 +43,7 @@ public:
void Clear();
dw_offset_t GetOffset() const { return m_offset; }
void Dump(lldb_private::Stream *s) const;
- bool Extract(const lldb_private::DataExtractor& data, lldb::offset_t *offset_ptr);
+ bool Extract(const lldb_private::DWARFDataExtractor& data, lldb::offset_t *offset_ptr);
//void Encode(BinaryStreamBuf& debug_abbrev_buf) const;
dw_uleb128_t AppendAbbrevDeclSequential(const DWARFAbbreviationDeclaration& abbrevDecl);
@@ -65,7 +65,7 @@ public:
DWARFDebugAbbrev();
const DWARFAbbreviationDeclarationSet* GetAbbreviationDeclarationSet(dw_offset_t cu_abbr_offset) const;
void Dump(lldb_private::Stream *s) const;
- void Parse(const lldb_private::DataExtractor& data);
+ void Parse(const lldb_private::DWARFDataExtractor& data);
protected:
DWARFAbbreviationDeclarationCollMap m_abbrevCollMap;
mutable DWARFAbbreviationDeclarationCollMapConstIter m_prev_abbr_offset_pos;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
index b1eb27299efb..d083f8a615c4 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
@@ -162,7 +162,7 @@ DWARFDebugArangeSet::AddDescriptor(const DWARFDebugArangeSet::Descriptor& range)
}
bool
-DWARFDebugArangeSet::Extract(const DataExtractor &data, lldb::offset_t *offset_ptr)
+DWARFDebugArangeSet::Extract(const DWARFDataExtractor &data, lldb::offset_t *offset_ptr)
{
if (data.ValidOffset(*offset_ptr))
{
@@ -183,9 +183,9 @@ DWARFDebugArangeSet::Extract(const DataExtractor &data, lldb::offset_t *offset_p
// descriptor on the target system. This header is followed by a series
// of tuples. Each tuple consists of an address and a length, each in
// the size appropriate for an address on the target architecture.
- m_header.length = data.GetU32(offset_ptr);
+ m_header.length = data.GetDWARFInitialLength(offset_ptr);
m_header.version = data.GetU16(offset_ptr);
- m_header.cu_offset = data.GetU32(offset_ptr);
+ m_header.cu_offset = data.GetDWARFOffset(offset_ptr);
m_header.addr_size = data.GetU8(offset_ptr);
m_header.seg_size = data.GetU8(offset_ptr);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
index 19ec8d042e72..fde36b7e0adc 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
@@ -41,7 +41,7 @@ public:
void SetHeader(uint16_t version, uint32_t cu_offset, uint8_t addr_size, uint8_t seg_size);
void AddDescriptor(const DWARFDebugArangeSet::Descriptor& range);
void Compact();
- bool Extract(const lldb_private::DataExtractor &data, lldb::offset_t *offset_ptr);
+ bool Extract(const lldb_private::DWARFDataExtractor &data, lldb::offset_t *offset_ptr);
void Dump(lldb_private::Stream *s) const;
dw_offset_t GetCompileUnitDIEOffset() const { return m_header.cu_offset; }
dw_offset_t GetOffsetOfNextEntry() const;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
index 3b004c4b3890..4f77bff86bdc 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
@@ -56,7 +56,7 @@ public:
// Extract
//----------------------------------------------------------------------
bool
-DWARFDebugAranges::Extract(const DataExtractor &debug_aranges_data)
+DWARFDebugAranges::Extract(const DWARFDataExtractor &debug_aranges_data)
{
if (debug_aranges_data.ValidOffset(0))
{
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
index 88db929226ab..206aa3a60f49 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
@@ -35,7 +35,7 @@ public:
}
bool
- Extract(const lldb_private::DataExtractor &debug_aranges_data);
+ Extract(const lldb_private::DWARFDataExtractor &debug_aranges_data);
bool
Generate(SymbolFileDWARF* dwarf2Data);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 4c76eed8166f..d4db12c17a40 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -57,7 +57,7 @@ DWARFDebugInfo::GetCompileUnitAranges ()
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
m_cu_aranges_ap.reset (new DWARFDebugAranges());
- const DataExtractor &debug_aranges_data = m_dwarf2Data->get_debug_aranges_data();
+ const DWARFDataExtractor &debug_aranges_data = m_dwarf2Data->get_debug_aranges_data();
if (debug_aranges_data.GetByteSize() > 0)
{
if (log)
@@ -66,18 +66,35 @@ DWARFDebugInfo::GetCompileUnitAranges ()
m_cu_aranges_ap->Extract (debug_aranges_data);
}
- else
+
+ // Make a list of all CUs represented by the arange data in the file.
+ std::set<dw_offset_t> cus_with_data;
+ for (size_t n=0;n<m_cu_aranges_ap.get()->GetNumRanges();n++)
{
- if (log)
- log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing",
- m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
- 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)
+ dw_offset_t offset = m_cu_aranges_ap.get()->OffsetAtIndex(n);
+ if (offset != DW_INVALID_OFFSET)
+ cus_with_data.insert (offset);
+ }
+
+ // 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);
+
+ dw_offset_t offset = cu->GetOffset();
+ if (cus_with_data.find(offset) == cus_with_data.end())
{
- DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx);
- if (cu)
- cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get(), clear_dies_if_already_not_parsed);
+ if (log)
+ {
+ if (!printed)
+ log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing",
+ m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
+ printed = true;
+ }
+ cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get(), clear_dies_if_already_not_parsed);
}
}
@@ -146,7 +163,7 @@ DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded()
if (m_dwarf2Data != NULL)
{
lldb::offset_t offset = 0;
- const DataExtractor &debug_info_data = m_dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = m_dwarf2Data->get_debug_info_data();
while (debug_info_data.ValidOffset(offset))
{
DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data));
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index 03c12e366f92..37741eb1da9c 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -116,7 +116,7 @@ DWARFDebugInfoEntry::Attributes::FormValueAsUnsignedAtIndex(SymbolFileDWARF* dwa
bool
DWARFDebugInfoEntry::FastExtract
(
- const DataExtractor& debug_info_data,
+ const DWARFDataExtractor& debug_info_data,
const DWARFCompileUnit* cu,
const uint8_t *fixed_form_sizes,
lldb::offset_t *offset_ptr
@@ -151,8 +151,8 @@ DWARFDebugInfoEntry::FastExtract
m_has_children = abbrevDecl->HasChildren();
// Skip all data in the .debug_info for the attributes
const uint32_t numAttributes = abbrevDecl->NumAttributes();
- register uint32_t i;
- register dw_form_t form;
+ uint32_t i;
+ dw_form_t form;
for (i=0; i<numAttributes; ++i)
{
form = abbrevDecl->GetFormByIndexUnchecked(i);
@@ -166,7 +166,7 @@ DWARFDebugInfoEntry::FastExtract
do
{
form_is_indirect = false;
- register uint32_t form_size = 0;
+ uint32_t form_size = 0;
switch (form)
{
// Blocks if inlined data that have a length field and the data bytes
@@ -281,8 +281,8 @@ DWARFDebugInfoEntry::Extract
lldb::offset_t *offset_ptr
)
{
- const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
-// const DataExtractor& debug_str_data = dwarf2Data->get_debug_str_data();
+ const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+// const DWARFDataExtractor& debug_str_data = dwarf2Data->get_debug_str_data();
const uint32_t cu_end_offset = cu->GetNextCompileUnitOffset();
const uint8_t cu_addr_size = cu->GetAddressByteSize();
lldb::offset_t offset = *offset_ptr;
@@ -332,7 +332,7 @@ DWARFDebugInfoEntry::Extract
do
{
form_is_indirect = false;
- register uint32_t form_size = 0;
+ uint32_t form_size = 0;
switch (form)
{
// Blocks if inlined data that have a length field and the data bytes
@@ -591,7 +591,7 @@ DWARFDebugInfoEntry::DumpAncestry
// // The number of attributes are the same...
// if (a_attr_count > 0)
// {
-// const DataExtractor* debug_str_data_ptr = &dwarf2Data->get_debug_str_data();
+// const DWARFDataExtractor* debug_str_data_ptr = &dwarf2Data->get_debug_str_data();
//
// uint32_t i;
// for (i=0; i<a_attr_count; ++i)
@@ -763,9 +763,11 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
lldb::offset_t offset;
const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
+ lldb::ModuleSP module = dwarf2Data->GetObjectFile()->GetModule();
+
if (abbrevDecl)
{
- const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
if (!debug_info_data.ValidOffset(offset))
return false;
@@ -874,17 +876,17 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
{
uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
- frame_base->SetOpcodeData(debug_info_data, block_offset, block_length);
+ frame_base->SetOpcodeData(module, debug_info_data, block_offset, block_length);
}
else
{
- const DataExtractor &debug_loc_data = dwarf2Data->get_debug_loc_data();
+ const DWARFDataExtractor &debug_loc_data = dwarf2Data->get_debug_loc_data();
const dw_offset_t debug_loc_offset = form_value.Unsigned();
size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
if (loc_list_length > 0)
{
- frame_base->SetOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length);
+ frame_base->SetOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length);
if (lo_pc != LLDB_INVALID_ADDRESS)
{
assert (lo_pc >= cu->GetBaseAddress());
@@ -959,7 +961,7 @@ DWARFDebugInfoEntry::Dump
uint32_t recurse_depth
) const
{
- const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
lldb::offset_t offset = m_offset;
if (debug_info_data.ValidOffset(offset))
@@ -1053,7 +1055,7 @@ DWARFDebugInfoEntry::DumpAttribute
(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
- const DataExtractor& debug_info_data,
+ const DWARFDataExtractor& debug_info_data,
lldb::offset_t *offset_ptr,
Stream &s,
dw_attr_t attr,
@@ -1063,7 +1065,7 @@ DWARFDebugInfoEntry::DumpAttribute
bool verbose = s.GetVerbose();
bool show_form = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm);
- const DataExtractor* debug_str_data = dwarf2Data ? &dwarf2Data->get_debug_str_data() : NULL;
+ const DWARFDataExtractor* debug_str_data = dwarf2Data ? &dwarf2Data->get_debug_str_data() : NULL;
if (verbose)
s.Offset (*offset_ptr);
else
@@ -1131,7 +1133,7 @@ DWARFDebugInfoEntry::DumpAttribute
form_value.Dump(s, debug_str_data, cu);
// Location description is inlined in data in the form value
- DataExtractor locationData(debug_info_data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned());
+ DWARFDataExtractor locationData(debug_info_data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned());
if ( verbose ) s.PutCString(" ( ");
print_dwarf_expression (s, locationData, DWARFCompileUnit::GetAddressByteSize(cu), 4, false);
if ( verbose ) s.PutCString(" )");
@@ -1221,7 +1223,7 @@ DWARFDebugInfoEntry::GetAttributes
if (abbrevDecl)
{
- const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
if (fixed_form_sizes == NULL)
fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize());
@@ -1322,7 +1324,7 @@ DWARFDebugInfoEntry::GetAttributeValue
if (attr_idx != DW_INVALID_INDEX)
{
- const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
uint32_t idx=0;
while (idx<attr_idx)
@@ -1495,7 +1497,7 @@ DWARFDebugInfoEntry::GetAttributeValueAsLocation
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- DataExtractor& location_data,
+ DWARFDataExtractor& location_data,
uint32_t &block_size
) const
{
@@ -1512,7 +1514,7 @@ DWARFDebugInfoEntry::GetAttributeValueAsLocation
if (blockData)
{
// We have an inlined location list in the .debug_info section
- const DataExtractor& debug_info = dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor& debug_info = dwarf2Data->get_debug_info_data();
dw_offset_t block_offset = blockData - debug_info.GetDataStart();
block_size = (end_addr_offset - attr_offset) - form_value.Unsigned();
location_data.SetData(debug_info, block_offset, block_size);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index 85f4109ae01a..f74057555286 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -142,7 +142,7 @@ public:
DWARFDebugAranges* debug_aranges) const;
bool FastExtract(
- const lldb_private::DataExtractor& debug_info_data,
+ const lldb_private::DWARFDataExtractor& debug_info_data,
const DWARFCompileUnit* cu,
const uint8_t *fixed_form_sizes,
lldb::offset_t* offset_ptr);
@@ -214,7 +214,7 @@ public:
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- lldb_private::DataExtractor& data,
+ lldb_private::DWARFDataExtractor& data,
uint32_t &block_size) const;
const char* GetName(
@@ -289,7 +289,7 @@ public:
static void DumpAttribute(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
- const lldb_private::DataExtractor& debug_info_data,
+ const lldb_private::DWARFDataExtractor& debug_info_data,
lldb::offset_t *offset_ptr,
lldb_private::Stream &s,
dw_attr_t attr,
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
index 6c9336a08426..0a2f1f749409 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
@@ -32,7 +32,7 @@ using namespace std;
// representation.
//----------------------------------------------------------------------
void
-DWARFDebugLine::Parse(const DataExtractor& debug_line_data)
+DWARFDebugLine::Parse(const DWARFDataExtractor& debug_line_data)
{
m_lineTableMap.clear();
lldb::offset_t offset = 0;
@@ -59,7 +59,7 @@ DWARFDebugLine::Parse(const DataExtractor& debug_line_data)
}
void
-DWARFDebugLine::ParseIfNeeded(const DataExtractor& debug_line_data)
+DWARFDebugLine::ParseIfNeeded(const DWARFDataExtractor& debug_line_data)
{
if (m_lineTableMap.empty())
Parse(debug_line_data);
@@ -110,7 +110,7 @@ DumpStateToFile (dw_offset_t offset, const DWARFDebugLine::State& state, void* u
bool
DWARFDebugLine::DumpLineTableRows(Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t debug_line_offset)
{
- const DataExtractor& debug_line_data = dwarf2Data->get_debug_line_data();
+ const DWARFDataExtractor& debug_line_data = dwarf2Data->get_debug_line_data();
if (debug_line_offset == DW_INVALID_OFFSET)
{
@@ -131,7 +131,7 @@ DWARFDebugLine::DumpLineTableRows(Log *log, SymbolFileDWARF* dwarf2Data, dw_offs
// DWARFDebugLine::DumpStatementTable
//----------------------------------------------------------------------
dw_offset_t
-DWARFDebugLine::DumpStatementTable(Log *log, const DataExtractor& debug_line_data, const dw_offset_t debug_line_offset)
+DWARFDebugLine::DumpStatementTable(Log *log, const DWARFDataExtractor& debug_line_data, const dw_offset_t debug_line_offset)
{
if (debug_line_data.ValidOffset(debug_line_offset))
{
@@ -156,7 +156,7 @@ DWARFDebugLine::DumpStatementTable(Log *log, const DataExtractor& debug_line_dat
bool
DWARFDebugLine::DumpOpcodes(Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t debug_line_offset, uint32_t dump_flags)
{
- const DataExtractor& debug_line_data = dwarf2Data->get_debug_line_data();
+ const DWARFDataExtractor& debug_line_data = dwarf2Data->get_debug_line_data();
if (debug_line_data.GetByteSize() == 0)
{
@@ -183,7 +183,7 @@ DWARFDebugLine::DumpOpcodes(Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t d
// DumpStatementOpcodes
//----------------------------------------------------------------------
dw_offset_t
-DWARFDebugLine::DumpStatementOpcodes(Log *log, const DataExtractor& debug_line_data, const dw_offset_t debug_line_offset, uint32_t flags)
+DWARFDebugLine::DumpStatementOpcodes(Log *log, const DWARFDataExtractor& debug_line_data, const dw_offset_t debug_line_offset, uint32_t flags)
{
lldb::offset_t offset = debug_line_offset;
if (debug_line_data.ValidOffset(offset))
@@ -386,7 +386,7 @@ DWARFDebugLine::DumpStatementOpcodes(Log *log, const DataExtractor& debug_line_d
// the line table.
//----------------------------------------------------------------------
void
-DWARFDebugLine::Parse(const DataExtractor& debug_line_data, DWARFDebugLine::State::Callback callback, void* userData)
+DWARFDebugLine::Parse(const DWARFDataExtractor& debug_line_data, DWARFDebugLine::State::Callback callback, void* userData)
{
lldb::offset_t offset = 0;
if (debug_line_data.ValidOffset(offset))
@@ -401,7 +401,7 @@ DWARFDebugLine::Parse(const DataExtractor& debug_line_data, DWARFDebugLine::Stat
// DWARFDebugLine::ParsePrologue
//----------------------------------------------------------------------
bool
-DWARFDebugLine::ParsePrologue(const DataExtractor& debug_line_data, lldb::offset_t* offset_ptr, Prologue* prologue)
+DWARFDebugLine::ParsePrologue(const DWARFDataExtractor& debug_line_data, lldb::offset_t* offset_ptr, Prologue* prologue)
{
const lldb::offset_t prologue_offset = *offset_ptr;
@@ -410,12 +410,12 @@ DWARFDebugLine::ParsePrologue(const DataExtractor& debug_line_data, lldb::offset
prologue->Clear();
uint32_t i;
const char * s;
- prologue->total_length = debug_line_data.GetU32(offset_ptr);
+ prologue->total_length = debug_line_data.GetDWARFInitialLength(offset_ptr);
prologue->version = debug_line_data.GetU16(offset_ptr);
if (prologue->version != 2)
return false;
- prologue->prologue_length = debug_line_data.GetU32(offset_ptr);
+ prologue->prologue_length = debug_line_data.GetDWARFOffset(offset_ptr);
const lldb::offset_t end_prologue_offset = prologue->prologue_length + *offset_ptr;
prologue->min_inst_length = debug_line_data.GetU8(offset_ptr);
prologue->default_is_stmt = debug_line_data.GetU8(offset_ptr);
@@ -456,10 +456,11 @@ DWARFDebugLine::ParsePrologue(const DataExtractor& debug_line_data, lldb::offset
break;
}
+ // XXX GNU as is broken for 64-Bit DWARF
if (*offset_ptr != end_prologue_offset)
{
Host::SystemLog (Host::eSystemLogWarning,
- "warning: parsing line table prologue at 0x%8.8" PRIx64 " should have ended at 0x%8.8" PRIx64 " but it ended ad 0x%8.8" PRIx64 "\n",
+ "warning: parsing line table prologue at 0x%8.8" PRIx64 " should have ended at 0x%8.8" PRIx64 " but it ended at 0x%8.8" PRIx64 "\n",
prologue_offset,
end_prologue_offset,
*offset_ptr);
@@ -469,18 +470,20 @@ DWARFDebugLine::ParsePrologue(const DataExtractor& debug_line_data, lldb::offset
bool
DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp,
- const DataExtractor& debug_line_data,
+ const DWARFDataExtractor& debug_line_data,
const char *cu_comp_dir,
dw_offset_t stmt_list,
FileSpecList &support_files)
{
- lldb::offset_t offset = stmt_list + 4; // Skip the total length
+ lldb::offset_t offset = stmt_list;
+ // Skip the total length
+ (void)debug_line_data.GetDWARFInitialLength(&offset);
const char * s;
uint32_t version = debug_line_data.GetU16(&offset);
if (version != 2)
return false;
- const dw_offset_t end_prologue_offset = debug_line_data.GetU32(&offset) + offset;
+ const dw_offset_t end_prologue_offset = debug_line_data.GetDWARFOffset(&offset) + offset;
// Skip instruction length, default is stmt, line base, line range and
// opcode base, and all opcode lengths
offset += 4;
@@ -554,7 +557,7 @@ DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp,
if (offset != end_prologue_offset)
{
Host::SystemLog (Host::eSystemLogError,
- "warning: parsing line table prologue at 0x%8.8x should have ended at 0x%8.8x but it ended ad 0x%8.8" PRIx64 "\n",
+ "warning: parsing line table prologue at 0x%8.8x should have ended at 0x%8.8x but it ended at 0x%8.8" PRIx64 "\n",
stmt_list,
end_prologue_offset,
offset);
@@ -572,7 +575,7 @@ DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp,
bool
DWARFDebugLine::ParseStatementTable
(
- const DataExtractor& debug_line_data,
+ const DWARFDataExtractor& debug_line_data,
lldb::offset_t* offset_ptr,
DWARFDebugLine::State::Callback callback,
void* userData
@@ -600,7 +603,7 @@ DWARFDebugLine::ParseStatementTable
if (log)
prologue->Dump (log);
- const dw_offset_t end_offset = debug_line_offset + prologue->total_length + sizeof(prologue->total_length);
+ const dw_offset_t end_offset = debug_line_offset + prologue->total_length + (debug_line_data.GetDWARFSizeofInitialLength());
State state(prologue, log, callback, userData);
@@ -873,7 +876,7 @@ ParseStatementTableCallback(dw_offset_t offset, const DWARFDebugLine::State& sta
// the prologue and all rows.
//----------------------------------------------------------------------
bool
-DWARFDebugLine::ParseStatementTable(const DataExtractor& debug_line_data, lldb::offset_t *offset_ptr, LineTable* line_table)
+DWARFDebugLine::ParseStatementTable(const DWARFDataExtractor& debug_line_data, lldb::offset_t *offset_ptr, LineTable* line_table)
{
return ParseStatementTable(debug_line_data, offset_ptr, ParseStatementTableCallback, line_table);
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
index cfa8654ed9ba..0caaf596add5 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
@@ -16,6 +16,7 @@
#include "lldb/lldb-private.h"
+#include "DWARFDataExtractor.h"
#include "DWARFDefines.h"
class SymbolFileDWARF;
@@ -82,10 +83,6 @@ public:
std::vector<std::string> include_directories;
std::vector<FileNameEntry> file_names;
- // Length of the prologue in bytes
- uint32_t Length() const { return prologue_length + sizeof(total_length) + sizeof(version) + sizeof(prologue_length); }
- // Length of the line table data in bytes (not including the prologue)
- uint32_t StatementTableLength() const { return total_length + sizeof(total_length) - Length(); }
int32_t MaxLineIncrementForSpecialOpcode() const { return line_base + (int8_t)line_range - 1; }
bool IsValid() const;
// void Append(BinaryStreamBuf& buff) const;
@@ -196,13 +193,13 @@ public:
static bool DumpOpcodes(lldb_private::Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t line_offset = DW_INVALID_OFFSET, uint32_t dump_flags = 0); // If line_offset is invalid, dump everything
static bool DumpLineTableRows(lldb_private::Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t line_offset = DW_INVALID_OFFSET); // If line_offset is invalid, dump everything
- static bool ParseSupportFiles(const lldb::ModuleSP &module_sp, const lldb_private::DataExtractor& debug_line_data, const char *cu_comp_dir, dw_offset_t stmt_list, lldb_private::FileSpecList &support_files);
- static bool ParsePrologue(const lldb_private::DataExtractor& debug_line_data, lldb::offset_t* offset_ptr, Prologue* prologue);
- static bool ParseStatementTable(const lldb_private::DataExtractor& debug_line_data, lldb::offset_t* offset_ptr, State::Callback callback, void* userData);
- static dw_offset_t DumpStatementTable(lldb_private::Log *log, const lldb_private::DataExtractor& debug_line_data, const dw_offset_t line_offset);
- static dw_offset_t DumpStatementOpcodes(lldb_private::Log *log, const lldb_private::DataExtractor& debug_line_data, const dw_offset_t line_offset, uint32_t flags);
- static bool ParseStatementTable(const lldb_private::DataExtractor& debug_line_data, lldb::offset_t *offset_ptr, LineTable* line_table);
- static void Parse(const lldb_private::DataExtractor& debug_line_data, DWARFDebugLine::State::Callback callback, void* userData);
+ static bool ParseSupportFiles(const lldb::ModuleSP &module_sp, const lldb_private::DWARFDataExtractor& debug_line_data, const char *cu_comp_dir, dw_offset_t stmt_list, lldb_private::FileSpecList &support_files);
+ static bool ParsePrologue(const lldb_private::DWARFDataExtractor& debug_line_data, lldb::offset_t* offset_ptr, Prologue* prologue);
+ static bool ParseStatementTable(const lldb_private::DWARFDataExtractor& debug_line_data, lldb::offset_t* offset_ptr, State::Callback callback, void* userData);
+ static dw_offset_t DumpStatementTable(lldb_private::Log *log, const lldb_private::DWARFDataExtractor& debug_line_data, const dw_offset_t line_offset);
+ static dw_offset_t DumpStatementOpcodes(lldb_private::Log *log, const lldb_private::DWARFDataExtractor& debug_line_data, const dw_offset_t line_offset, uint32_t flags);
+ static bool ParseStatementTable(const lldb_private::DWARFDataExtractor& debug_line_data, lldb::offset_t *offset_ptr, LineTable* line_table);
+ static void Parse(const lldb_private::DWARFDataExtractor& debug_line_data, DWARFDebugLine::State::Callback callback, void* userData);
// static void AppendLineTableData(const DWARFDebugLine::Prologue* prologue, const DWARFDebugLine::Row::collection& state_coll, const uint32_t addr_size, BinaryStreamBuf &debug_line_data);
DWARFDebugLine() :
@@ -210,8 +207,8 @@ public:
{
}
- void Parse(const lldb_private::DataExtractor& debug_line_data);
- void ParseIfNeeded(const lldb_private::DataExtractor& debug_line_data);
+ void Parse(const lldb_private::DWARFDataExtractor& debug_line_data);
+ void ParseIfNeeded(const lldb_private::DWARFDataExtractor& debug_line_data);
LineTable::shared_ptr GetLineTable(const dw_offset_t offset) const;
protected:
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp
index 60ace9e82290..0e2aaa47e8c9 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp
@@ -26,7 +26,7 @@ DWARFDebugMacinfo::~DWARFDebugMacinfo()
}
void
-DWARFDebugMacinfo::Dump(Stream *s, const DataExtractor& macinfo_data, lldb::offset_t offset)
+DWARFDebugMacinfo::Dump(Stream *s, const DWARFDataExtractor& macinfo_data, lldb::offset_t offset)
{
DWARFDebugMacinfoEntry maninfo_entry;
if (macinfo_data.GetByteSize() == 0)
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h
index 5f3b437d964f..077718cf7db2 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h
@@ -21,7 +21,7 @@ public:
static void
Dump (lldb_private::Stream *s,
- const lldb_private::DataExtractor& macinfo_data,
+ const lldb_private::DWARFDataExtractor& macinfo_data,
lldb::offset_t offset = LLDB_INVALID_OFFSET);
};
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp
index 5cd9cb6be474..4a176bb8aad4 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp
@@ -80,7 +80,7 @@ DWARFDebugMacinfoEntry::Dump(Stream *s) const
bool
-DWARFDebugMacinfoEntry::Extract(const DataExtractor& mac_info_data, lldb::offset_t* offset_ptr)
+DWARFDebugMacinfoEntry::Extract(const DWARFDataExtractor& mac_info_data, lldb::offset_t* offset_ptr)
{
if (mac_info_data.ValidOffset(*offset_ptr))
{
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h
index 46fd44a22a63..72318d86e1ca 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h
@@ -38,7 +38,7 @@ public:
GetCString() const;
bool
- Extract(const lldb_private::DataExtractor& mac_info_data,
+ Extract(const lldb_private::DWARFDataExtractor& mac_info_data,
lldb::offset_t* offset_ptr);
protected:
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
index 3e511007a1ec..06ac825e0d4d 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
@@ -29,7 +29,7 @@ DWARFDebugPubnames::DWARFDebugPubnames() :
}
bool
-DWARFDebugPubnames::Extract(const DataExtractor& data)
+DWARFDebugPubnames::Extract(const DWARFDataExtractor& data)
{
Timer scoped_timer (__PRETTY_FUNCTION__,
"DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
@@ -77,7 +77,7 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
if (debug_info)
{
- const DataExtractor* debug_str = &dwarf2Data->get_debug_str_data();
+ const DWARFDataExtractor* debug_str = &dwarf2Data->get_debug_str_data();
uint32_t cu_idx = 0;
const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h
index 09eb80ab3006..cacb1ea109bf 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h
@@ -20,7 +20,7 @@ class DWARFDebugPubnames
{
public:
DWARFDebugPubnames();
- bool Extract(const lldb_private::DataExtractor& data);
+ bool Extract(const lldb_private::DWARFDataExtractor& data);
bool GeneratePubnames(SymbolFileDWARF* dwarf2Data);
bool GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp
index 2df8d525f03f..b7e1b27d1501 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp
@@ -78,21 +78,21 @@ DWARFDebugPubnamesSet::InitNameIndexes() const
bool
-DWARFDebugPubnamesSet::Extract(const DataExtractor& data, lldb::offset_t *offset_ptr)
+DWARFDebugPubnamesSet::Extract(const DWARFDataExtractor& data, lldb::offset_t *offset_ptr)
{
if (data.ValidOffset(*offset_ptr))
{
m_descriptors.clear();
m_offset = *offset_ptr;
- m_header.length = data.GetU32(offset_ptr);
+ m_header.length = data.GetDWARFInitialLength(offset_ptr);
m_header.version = data.GetU16(offset_ptr);
- m_header.die_offset = data.GetU32(offset_ptr);
- m_header.die_length = data.GetU32(offset_ptr);
+ m_header.die_offset = data.GetDWARFOffset(offset_ptr);
+ m_header.die_length = data.GetDWARFOffset(offset_ptr);
Descriptor pubnameDesc;
while (data.ValidOffset(*offset_ptr))
{
- pubnameDesc.offset = data.GetU32(offset_ptr);
+ pubnameDesc.offset = data.GetDWARFOffset(offset_ptr);
if (pubnameDesc.offset)
{
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h
index 941c83e58a44..075807b2dcc3 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h
@@ -13,7 +13,7 @@
#include "SymbolFileDWARF.h"
#include <string>
#include <vector>
-#if __cplusplus >= 201103L
+#if __cplusplus >= 201103L || defined(_MSC_VER)
#include <unordered_map>
#else
#include <ext/hash_map>
@@ -70,7 +70,7 @@ public:
uint32_t NumDescriptors() const { return m_descriptors.size(); }
void AddDescriptor(dw_offset_t cu_rel_offset, const char* name);
void Clear();
- bool Extract(const lldb_private::DataExtractor& debug_pubnames_data, lldb::offset_t *offset_ptr);
+ bool Extract(const lldb_private::DWARFDataExtractor& debug_pubnames_data, lldb::offset_t *offset_ptr);
void Dump(lldb_private::Log *s) const;
void InitNameIndexes() const;
void Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offset_coll) const;
@@ -87,7 +87,7 @@ protected:
dw_offset_t m_offset;
Header m_header;
-#if __cplusplus >= 201103L
+#if __cplusplus >= 201103L || defined(_MSC_VER)
typedef std::unordered_multimap<const char*, uint32_t, std::hash<const char*>, CStringEqualBinaryPredicate> cstr_to_index_mmap;
#else
typedef __gnu_cxx::hash_multimap<const char*, uint32_t, __gnu_cxx::hash<const char*>, CStringEqualBinaryPredicate> cstr_to_index_mmap;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
index 461b17fc3aba..a4968c455a68 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
@@ -87,7 +87,7 @@ DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_pt
range_list.Clear();
lldb::offset_t range_offset = *offset_ptr;
- const DataExtractor& debug_ranges_data = dwarf2Data->get_debug_ranges_data();
+ const DWARFDataExtractor& debug_ranges_data = dwarf2Data->get_debug_ranges_data();
uint32_t addr_size = debug_ranges_data.GetAddressByteSize();
while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size))
@@ -132,7 +132,7 @@ DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_pt
void
-DWARFDebugRanges::Dump(Stream &s, const DataExtractor& debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr)
+DWARFDebugRanges::Dump(Stream &s, const DWARFDataExtractor& debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr)
{
uint32_t addr_size = s.GetAddressByteSize();
bool verbose = s.GetVerbose();
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
index 40899abe9c25..50af91d41009 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
@@ -26,7 +26,7 @@ public:
DWARFDebugRanges();
~DWARFDebugRanges();
void Extract(SymbolFileDWARF* dwarf2Data);
- static void Dump(lldb_private::Stream &s, const lldb_private::DataExtractor& debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr);
+ static void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor& debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr);
bool FindRanges(dw_offset_t debug_ranges_offset, DWARFDebugRanges::RangeList& range_list) const;
protected:
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
index accd3446317a..2be5d90c37b2 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
@@ -54,7 +54,7 @@ public:
}
// Test operator
- operator bool() const
+ explicit operator bool() const
{
return tag != 0;
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDefines.h b/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
index e37aefb27a72..d47e6a350c93 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
@@ -11,7 +11,6 @@
#define SymbolFileDWARF_DWARFDefines_h_
#include <stdint.h>
-#include <stdbool.h>
#include "lldb/Core/dwarf.h"
namespace lldb_private {
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index 6113a146c93d..abd273770ddc 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -114,7 +114,7 @@ DWARFFormValue::DWARFFormValue(dw_form_t form) :
}
bool
-DWARFFormValue::ExtractValue(const DataExtractor& data, lldb::offset_t* offset_ptr, const DWARFCompileUnit* cu)
+DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* offset_ptr, const DWARFCompileUnit* cu)
{
bool indirect = false;
bool is_block = false;
@@ -183,13 +183,13 @@ DWARFFormValue::ExtractValue(const DataExtractor& data, lldb::offset_t* offset_p
}
bool
-DWARFFormValue::SkipValue(const DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) const
+DWARFFormValue::SkipValue(const DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) const
{
return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, cu);
}
bool
-DWARFFormValue::SkipValue(dw_form_t form, const DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu)
+DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu)
{
switch (form)
{
@@ -278,7 +278,7 @@ DWARFFormValue::SkipValue(dw_form_t form, const DataExtractor& debug_info_data,
void
-DWARFFormValue::Dump(Stream &s, const DataExtractor* debug_str_data, const DWARFCompileUnit* cu) const
+DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data, const DWARFCompileUnit* cu) const
{
uint64_t uvalue = Unsigned();
bool cu_relative_offset = false;
@@ -378,7 +378,7 @@ DWARFFormValue::Dump(Stream &s, const DataExtractor* debug_str_data, const DWARF
}
const char*
-DWARFFormValue::AsCString(const DataExtractor* debug_str_data_ptr) const
+DWARFFormValue::AsCString(const DWARFDataExtractor* debug_str_data_ptr) const
{
if (IsInlinedCStr())
return m_value.value.cstr;
@@ -496,7 +496,7 @@ DWARFFormValue::IsDataForm(const dw_form_t form)
}
int
-DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const DataExtractor* debug_str_data_ptr)
+DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const DWARFDataExtractor* debug_str_data_ptr)
{
dw_form_t a_form = a_value.Form();
dw_form_t b_form = b_value.Form();
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index 4c400b2df58e..fce995e4ff2e 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -11,6 +11,7 @@
#define SymbolFileDWARF_DWARFFormValue_h_
#include <stddef.h> // for NULL
+#include "DWARFDataExtractor.h"
class DWARFCompileUnit;
@@ -48,8 +49,8 @@ public:
dw_form_t Form() const { return m_form; }
void SetForm(dw_form_t form) { m_form = form; }
const ValueType& Value() const { return m_value; }
- void Dump(lldb_private::Stream &s, const lldb_private::DataExtractor* debug_str_data, const DWARFCompileUnit* cu) const;
- bool ExtractValue(const lldb_private::DataExtractor& data,
+ void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor* debug_str_data, const DWARFCompileUnit* cu) const;
+ bool ExtractValue(const lldb_private::DWARFDataExtractor& data,
lldb::offset_t* offset_ptr,
const DWARFCompileUnit* cu);
bool IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (uint8_t*)m_value.value.cstr; }
@@ -62,16 +63,16 @@ public:
void SetUnsigned(uint64_t uval) { m_value.value.uval = uval; }
int64_t Signed() const { return m_value.value.sval; }
void SetSigned(int64_t sval) { m_value.value.sval = sval; }
- const char* AsCString(const lldb_private::DataExtractor* debug_str_data_ptr) const;
- bool SkipValue(const lldb_private::DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) const;
- static bool SkipValue(const dw_form_t form, const lldb_private::DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu);
-// static bool TransferValue(dw_form_t form, const lldb_private::DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff);
+ const char* AsCString(const lldb_private::DWARFDataExtractor* debug_str_data_ptr) const;
+ bool SkipValue(const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) const;
+ static bool SkipValue(const dw_form_t form, const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu);
+// static bool TransferValue(dw_form_t form, const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff);
// static bool TransferValue(const DWARFFormValue& formValue, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff);
// static bool PutUnsigned(dw_form_t form, dw_offset_t offset, uint64_t value, BinaryStreamBuf& out_buff, const DWARFCompileUnit* cu, bool fixup_cu_relative_refs);
static bool IsBlockForm(const dw_form_t form);
static bool IsDataForm(const dw_form_t form);
static const uint8_t * GetFixedFormSizesForAddressSize (uint8_t addr_size);
- static int Compare (const DWARFFormValue& a, const DWARFFormValue& b, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const lldb_private::DataExtractor* debug_str_data_ptr);
+ static int Compare (const DWARFFormValue& a, const DWARFFormValue& b, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const lldb_private::DWARFDataExtractor* debug_str_data_ptr);
protected:
dw_form_t m_form; // Form for this value
ValueType m_value; // Contains all data for the form
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp
index fdc07836b88d..d79ae79822b0 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp
@@ -15,11 +15,11 @@
using namespace lldb_private;
-static int print_dwarf_exp_op (Stream &s, const DataExtractor& data, lldb::offset_t *offset_ptr, int address_size, int dwarf_ref_size);
+static int print_dwarf_exp_op (Stream &s, const DWARFDataExtractor& data, lldb::offset_t *offset_ptr, int address_size, int dwarf_ref_size);
int
print_dwarf_expression (Stream &s,
- const DataExtractor& data,
+ const DWARFDataExtractor& data,
int address_size,
int dwarf_ref_size,
bool location_expression)
@@ -47,7 +47,7 @@ print_dwarf_expression (Stream &s,
static int
print_dwarf_exp_op (Stream &s,
- const DataExtractor& data,
+ const DWARFDataExtractor& data,
lldb::offset_t *offset_ptr,
int address_size,
int dwarf_ref_size)
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h
index ff7c907e921c..69cc0c15969c 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h
@@ -14,7 +14,7 @@
int
print_dwarf_expression (lldb_private::Stream &s,
- const lldb_private::DataExtractor& data,
+ const lldb_private::DWARFDataExtractor& data,
int address_size,
int dwarf_ref_size,
bool location_expression);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp
index dad5691267df..26768f060ef1 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp
@@ -18,7 +18,7 @@
using namespace lldb_private;
dw_offset_t
-DWARFLocationList::Dump(Stream &s, const DWARFCompileUnit* cu, const DataExtractor& debug_loc_data, lldb::offset_t offset)
+DWARFLocationList::Dump(Stream &s, const DWARFCompileUnit* cu, const DWARFDataExtractor& debug_loc_data, lldb::offset_t offset)
{
uint64_t start_addr, end_addr;
uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu);
@@ -42,7 +42,7 @@ DWARFLocationList::Dump(Stream &s, const DWARFCompileUnit* cu, const DataExtract
": ");
uint32_t loc_length = debug_loc_data.GetU16(&offset);
- DataExtractor locationData(debug_loc_data, offset, loc_length);
+ DWARFDataExtractor locationData(debug_loc_data, offset, loc_length);
// if ( dump_flags & DWARFDebugInfo::eDumpFlag_Verbose ) *ostrm_ptr << " ( ";
print_dwarf_expression (s, locationData, addr_size, 4, false);
offset += loc_length;
@@ -52,7 +52,7 @@ DWARFLocationList::Dump(Stream &s, const DWARFCompileUnit* cu, const DataExtract
}
bool
-DWARFLocationList::Extract(const DataExtractor& debug_loc_data, lldb::offset_t* offset_ptr, DataExtractor& location_list_data)
+DWARFLocationList::Extract(const DWARFDataExtractor& debug_loc_data, lldb::offset_t* offset_ptr, DWARFDataExtractor& location_list_data)
{
// Initialize with no data just in case we don't find anything
location_list_data.Clear();
@@ -69,7 +69,7 @@ DWARFLocationList::Extract(const DataExtractor& debug_loc_data, lldb::offset_t*
}
size_t
-DWARFLocationList::Size(const DataExtractor& debug_loc_data, lldb::offset_t offset)
+DWARFLocationList::Size(const DWARFDataExtractor& debug_loc_data, lldb::offset_t offset)
{
const dw_offset_t debug_loc_offset = offset;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h
index 85e11d90b36b..6dcc0d74e441 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h
@@ -18,16 +18,16 @@ public:
static dw_offset_t
Dump (lldb_private::Stream &s,
const DWARFCompileUnit* cu,
- const lldb_private::DataExtractor& debug_loc_data,
+ const lldb_private::DWARFDataExtractor& debug_loc_data,
lldb::offset_t offset);
static bool
- Extract (const lldb_private::DataExtractor& debug_loc_data,
+ Extract (const lldb_private::DWARFDataExtractor& debug_loc_data,
lldb::offset_t* offset_ptr,
- lldb_private::DataExtractor& location_list_data);
+ lldb_private::DWARFDataExtractor& location_list_data);
static size_t
- Size (const lldb_private::DataExtractor& debug_loc_data,
+ Size (const lldb_private::DWARFDataExtractor& debug_loc_data,
lldb::offset_t offset);
};
diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
index c31cbaf3ca20..44a24f2756ad 100644
--- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
+++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -432,7 +432,7 @@ struct DWARFMappedHash
}
bool
- Read (const lldb_private::DataExtractor &data,
+ Read (const lldb_private::DWARFDataExtractor &data,
lldb::offset_t *offset_ptr,
DIEInfo &hash_data) const
{
@@ -585,8 +585,8 @@ struct DWARFMappedHash
{
public:
- MemoryTable (lldb_private::DataExtractor &table_data,
- const lldb_private::DataExtractor &string_table,
+ MemoryTable (lldb_private::DWARFDataExtractor &table_data,
+ const lldb_private::DWARFDataExtractor &string_table,
const char *name) :
MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data),
m_data (table_data),
@@ -923,8 +923,8 @@ struct DWARFMappedHash
}
protected:
- const lldb_private::DataExtractor &m_data;
- const lldb_private::DataExtractor &m_string_table;
+ const lldb_private::DWARFDataExtractor &m_data;
+ const lldb_private::DWARFDataExtractor &m_string_table;
std::string m_name;
};
};
diff --git a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
index 27fa261813bb..c9ffa9ec781f 100644
--- a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
@@ -174,10 +174,11 @@ LogChannelDWARF::ListCategories (Stream *strm)
{
strm->Printf ("Logging categories for '%s':\n"
" all - turn on all available logging categories\n"
- " info - log the parsing if .debug_info\n"
- " line - log the parsing if .debug_line\n"
- " pubnames - log the parsing if .debug_pubnames\n"
- " pubtypes - log the parsing if .debug_pubtypes\n"
+ " info - log the parsing of .debug_info\n"
+ " line - log the parsing of .debug_line\n"
+ " pubnames - log the parsing of .debug_pubnames\n"
+ " pubtypes - log the parsing of .debug_pubtypes\n"
+ " aranges - log the parsing of .debug_aranges\n"
" lookups - log any lookups that happen by name, regex, or address\n"
" completion - log struct/unions/class type completions\n"
" map - log insertions of object files into DWARF debug maps\n",
diff --git a/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
index 5514469d0758..e4626900d816 100644
--- a/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ b/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -9,7 +9,6 @@
#include "NameToDIE.h"
#include "lldb/Core/ConstString.h"
-#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/RegularExpression.h"
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index f265af837eef..09b50531b8a9 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -70,7 +70,7 @@
#ifdef ENABLE_DEBUG_PRINTF
#include <stdio.h>
-#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
#endif
@@ -699,8 +699,8 @@ SymbolFileDWARF::CalculateAbilities ()
return abilities;
}
-const DataExtractor&
-SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type, DataExtractor &data)
+const DWARFDataExtractor&
+SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type, DWARFDataExtractor &data)
{
if (m_flags.IsClear (got_flag))
{
@@ -728,73 +728,73 @@ SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type,
return data;
}
-const DataExtractor&
+const DWARFDataExtractor&
SymbolFileDWARF::get_debug_abbrev_data()
{
return GetCachedSectionData (flagsGotDebugAbbrevData, eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev);
}
-const DataExtractor&
+const DWARFDataExtractor&
SymbolFileDWARF::get_debug_aranges_data()
{
return GetCachedSectionData (flagsGotDebugArangesData, eSectionTypeDWARFDebugAranges, m_data_debug_aranges);
}
-const DataExtractor&
+const DWARFDataExtractor&
SymbolFileDWARF::get_debug_frame_data()
{
return GetCachedSectionData (flagsGotDebugFrameData, eSectionTypeDWARFDebugFrame, m_data_debug_frame);
}
-const DataExtractor&
+const DWARFDataExtractor&
SymbolFileDWARF::get_debug_info_data()
{
return GetCachedSectionData (flagsGotDebugInfoData, eSectionTypeDWARFDebugInfo, m_data_debug_info);
}
-const DataExtractor&
+const DWARFDataExtractor&
SymbolFileDWARF::get_debug_line_data()
{
return GetCachedSectionData (flagsGotDebugLineData, eSectionTypeDWARFDebugLine, m_data_debug_line);
}
-const DataExtractor&
+const DWARFDataExtractor&
SymbolFileDWARF::get_debug_loc_data()
{
return GetCachedSectionData (flagsGotDebugLocData, eSectionTypeDWARFDebugLoc, m_data_debug_loc);
}
-const DataExtractor&
+const DWARFDataExtractor&
SymbolFileDWARF::get_debug_ranges_data()
{
return GetCachedSectionData (flagsGotDebugRangesData, eSectionTypeDWARFDebugRanges, m_data_debug_ranges);
}
-const DataExtractor&
+const DWARFDataExtractor&
SymbolFileDWARF::get_debug_str_data()
{
return GetCachedSectionData (flagsGotDebugStrData, eSectionTypeDWARFDebugStr, m_data_debug_str);
}
-const DataExtractor&
+const DWARFDataExtractor&
SymbolFileDWARF::get_apple_names_data()
{
return GetCachedSectionData (flagsGotAppleNamesData, eSectionTypeDWARFAppleNames, m_data_apple_names);
}
-const DataExtractor&
+const DWARFDataExtractor&
SymbolFileDWARF::get_apple_types_data()
{
return GetCachedSectionData (flagsGotAppleTypesData, eSectionTypeDWARFAppleTypes, m_data_apple_types);
}
-const DataExtractor&
+const DWARFDataExtractor&
SymbolFileDWARF::get_apple_namespaces_data()
{
return GetCachedSectionData (flagsGotAppleNamespacesData, eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces);
}
-const DataExtractor&
+const DWARFDataExtractor&
SymbolFileDWARF::get_apple_objc_data()
{
return GetCachedSectionData (flagsGotAppleObjCData, eSectionTypeDWARFAppleObjC, m_data_apple_objc);
@@ -806,7 +806,7 @@ SymbolFileDWARF::DebugAbbrev()
{
if (m_abbr.get() == NULL)
{
- const DataExtractor &debug_abbrev_data = get_debug_abbrev_data();
+ const DWARFDataExtractor &debug_abbrev_data = get_debug_abbrev_data();
if (debug_abbrev_data.GetByteSize() > 0)
{
m_abbr.reset(new DWARFDebugAbbrev());
@@ -1706,6 +1706,7 @@ SymbolFileDWARF::ParseChildMembers
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
uint32_t member_idx = 0;
BitfieldInfo last_field_info;
+ ModuleSP module = GetObjectFile()->GetModule();
for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
{
@@ -1762,13 +1763,14 @@ SymbolFileDWARF::ParseChildMembers
{
Value initialValue(0);
Value memberOffset(0);
- const DataExtractor& debug_info_data = get_debug_info_data();
+ const DWARFDataExtractor& debug_info_data = get_debug_info_data();
uint32_t block_length = form_value.Unsigned();
uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
if (DWARFExpression::Evaluate(NULL, // ExecutionContext *
NULL, // ClangExpressionVariableList *
NULL, // ClangExpressionDeclMap *
NULL, // RegisterContext *
+ module,
debug_info_data,
block_offset,
block_length,
@@ -2153,13 +2155,14 @@ SymbolFileDWARF::ParseChildMembers
{
Value initialValue(0);
Value memberOffset(0);
- const DataExtractor& debug_info_data = get_debug_info_data();
+ const DWARFDataExtractor& debug_info_data = get_debug_info_data();
uint32_t block_length = form_value.Unsigned();
uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
if (DWARFExpression::Evaluate (NULL,
NULL,
NULL,
NULL,
+ module,
debug_info_data,
block_offset,
block_length,
@@ -2214,12 +2217,17 @@ SymbolFileDWARF::ParseChildMembers
if (is_virtual)
{
- layout_info.vbase_offsets.insert(std::make_pair(class_clang_type.GetAsCXXRecordDecl(),
- clang::CharUnits::fromQuantity(member_byte_offset)));
+ // Do not specify any offset for virtual inheritance. The DWARF produced by clang doesn't
+ // give us a constant offset, but gives us a DWARF expressions that requires an actual object
+ // in memory. the DW_AT_data_member_location for a virtual base class looks like:
+ // DW_AT_data_member_location( DW_OP_dup, DW_OP_deref, DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref, DW_OP_plus )
+ // Given this, there is really no valid response we can give to clang for virtual base
+ // class offsets, and this should eventually be removed from LayoutRecordType() in the external
+ // AST source in clang.
}
else
{
- layout_info.base_offsets.insert(std::make_pair(class_clang_type.GetAsCXXRecordDecl(),
+ layout_info.base_offsets.insert(std::make_pair(base_class_clang_type.GetAsCXXRecordDecl(),
clang::CharUnits::fromQuantity(member_byte_offset)));
}
}
@@ -2460,22 +2468,21 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
if (class_language == eLanguageTypeObjC)
{
- std::string class_str (clang_type.GetTypeName());
- if (!class_str.empty())
+ ConstString class_name (clang_type.GetTypeName());
+ if (class_name)
{
DIEArray method_die_offsets;
if (m_using_apple_tables)
{
if (m_apple_objc_ap.get())
- m_apple_objc_ap->FindByName(class_str.c_str(), method_die_offsets);
+ m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets);
}
else
{
if (!m_indexed)
Index ();
- ConstString class_name (class_str.c_str());
m_objc_class_selectors_index.Find (class_name, method_die_offsets);
}
@@ -2497,7 +2504,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_objc accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, class_str.c_str());
+ die_offset, class_name.GetCString());
}
}
}
@@ -2621,7 +2628,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
}
}
- return clang_type;
+ return (bool)clang_type;
case DW_TAG_enumeration_type:
clang_type.StartTagDeclarationDefinition ();
@@ -2633,7 +2640,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), dwarf_cu, die);
}
clang_type.CompleteTagDeclarationDefinition ();
- return clang_type;
+ return (bool)clang_type;
default:
assert(false && "not a forward clang type decl!");
@@ -2845,7 +2852,7 @@ SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line,
for (cu_idx = 0; (dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx)) != NULL; ++cu_idx)
{
CompileUnit *dc_cu = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx);
- const bool full_match = file_spec.GetDirectory();
+ const bool full_match = (bool)file_spec.GetDirectory();
bool file_spec_matches_cu_file_spec = dc_cu != NULL && FileSpec::Equal(file_spec, *dc_cu, full_match);
if (check_inlines || file_spec_matches_cu_file_spec)
{
@@ -3096,7 +3103,7 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
}
if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
- return 0;
+ return 0;
DWARFDebugInfo* info = DebugInfo();
if (info == NULL)
@@ -3553,7 +3560,7 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
sc_list.Clear();
if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
- return 0;
+ return 0;
// If name is empty then we won't find anything.
if (name.IsEmpty())
@@ -3691,22 +3698,30 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
{
Type *type = sc.function->GetType();
- clang::DeclContext* decl_ctx = GetClangDeclContextContainingTypeUID (type->GetID());
- if (decl_ctx->isRecord())
+ if (type)
{
- if (name_type_mask & eFunctionNameTypeBase)
+ clang::DeclContext* decl_ctx = GetClangDeclContextContainingTypeUID (type->GetID());
+ if (decl_ctx->isRecord())
{
- sc_list.RemoveContextAtIndex(sc_list.GetSize()-1);
- keep_die = false;
+ if (name_type_mask & eFunctionNameTypeBase)
+ {
+ sc_list.RemoveContextAtIndex(sc_list.GetSize()-1);
+ keep_die = false;
+ }
+ }
+ else
+ {
+ if (name_type_mask & eFunctionNameTypeMethod)
+ {
+ sc_list.RemoveContextAtIndex(sc_list.GetSize()-1);
+ keep_die = false;
+ }
}
}
else
{
- if (name_type_mask & eFunctionNameTypeMethod)
- {
- sc_list.RemoveContextAtIndex(sc_list.GetSize()-1);
- keep_die = false;
- }
+ GetObjectFile()->GetModule()->ReportWarning ("function at die offset 0x%8.8x had no function type",
+ die_offset);
}
}
}
@@ -3736,8 +3751,9 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
{
FindFunctions (name, m_function_fullname_index, sc_list);
- // Temporary workaround for global/anonymous namespace functions on linux
-#if defined (__linux__)
+ // FIXME Temporary workaround for global/anonymous namespace
+ // functions on FreeBSD and Linux
+#if defined (__FreeBSD__) || defined (__linux__)
// If we didn't find any functions in the global namespace try
// looking in the basename index but ignore any returned
// functions that have a namespace (ie. mangled names starting with
@@ -3930,7 +3946,7 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
types.Clear();
if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
- return 0;
+ return 0;
DIEArray die_offsets;
@@ -4032,7 +4048,7 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,
}
if (!NamespaceDeclMatchesThisSymbolFile(parent_namespace_decl))
- return ClangNamespaceDecl();
+ return ClangNamespaceDecl();
ClangNamespaceDecl namespace_decl;
DWARFDebugInfo* info = DebugInfo();
@@ -4191,9 +4207,9 @@ SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc,
case DW_AT_location:
// if (form_value.BlockData())
// {
- // const DataExtractor& debug_info_data = debug_info();
+ // const DWARFDataExtractor& debug_info_data = debug_info();
// uint32_t block_length = form_value.Unsigned();
- // DataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length);
+ // DWARFDataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length);
// }
// else
// {
@@ -4831,17 +4847,16 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
if (try_resolving_type)
{
- if (must_be_implementation && type_cu->Supports_DW_AT_APPLE_objc_complete_type())
- try_resolving_type = type_die->GetAttributeValueAsUnsigned (this, type_cu, DW_AT_APPLE_objc_complete_type, 0);
+ if (must_be_implementation && type_cu->Supports_DW_AT_APPLE_objc_complete_type())
+ try_resolving_type = type_die->GetAttributeValueAsUnsigned (this, type_cu, DW_AT_APPLE_objc_complete_type, 0);
if (try_resolving_type)
{
Type *resolved_type = ResolveType (type_cu, type_die, false);
if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)
{
- DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ") from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n",
+ DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n",
MakeUserID(die->GetOffset()),
- MakeUserID(dwarf_cu->GetOffset()),
m_obj_file->GetFileSpec().GetFilename().AsCString(),
MakeUserID(type_die->GetOffset()),
MakeUserID(type_cu->GetOffset()));
@@ -5117,7 +5132,7 @@ SymbolFileDWARF::FindDefinitionTypeForDIE (DWARFCompileUnit* cu,
{
DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ") from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n",
MakeUserID(die->GetOffset()),
- MakeUserID(dwarf_cu->GetOffset()),
+ MakeUserID(cu->GetOffset()),
m_obj_file->GetFileSpec().GetFilename().AsCString(),
MakeUserID(type_die->GetOffset()),
MakeUserID(type_cu->GetOffset()));
@@ -5732,7 +5747,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
}
}
- DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8x\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid);
+ DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid);
switch (tag)
{
@@ -5892,12 +5907,12 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
{
case DW_AT_decl_file:
if (dwarf_cu->DW_AT_decl_file_attributes_are_invalid())
- {
- // llvm-gcc outputs invalid DW_AT_decl_file attributes that always
- // point to the compile unit file, so we clear this invalid value
- // so that we can still unique types efficiently.
+ {
+ // llvm-gcc outputs invalid DW_AT_decl_file attributes that always
+ // point to the compile unit file, so we clear this invalid value
+ // so that we can still unique types efficiently.
decl.SetFile(FileSpec ("<invalid>", false));
- }
+ }
else
decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned()));
break;
@@ -7255,6 +7270,7 @@ SymbolFileDWARF::ParseVariableDIE
return var_sp; // Already been parsed!
const dw_tag_t tag = die->Tag();
+ ModuleSP module = GetObjectFile()->GetModule();
if ((tag == DW_TAG_variable) ||
(tag == DW_TAG_constant) ||
@@ -7298,13 +7314,13 @@ SymbolFileDWARF::ParseVariableDIE
{
location_is_const_value_data = true;
// The constant value will be either a block, a data value or a string.
- const DataExtractor& debug_info_data = get_debug_info_data();
+ const DWARFDataExtractor& debug_info_data = get_debug_info_data();
if (DWARFFormValue::IsBlockForm(form_value.Form()))
{
// Retrieve the value as a block expression.
uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
- location.CopyOpcodeData(debug_info_data, block_offset, block_length);
+ location.CopyOpcodeData(module, debug_info_data, block_offset, block_length);
}
else if (DWARFFormValue::IsDataForm(form_value.Form()))
{
@@ -7312,7 +7328,7 @@ 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(debug_info_data, data_offset, data_length);
+ location.CopyOpcodeData(module, debug_info_data, data_offset, data_length);
}
else
{
@@ -7322,14 +7338,14 @@ 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(debug_info_data, data_offset, data_length);
+ location.CopyOpcodeData(module, debug_info_data, data_offset, data_length);
}
else
{
const char *str = form_value.AsCString(&debug_info_data);
uint32_t string_offset = str - (const char *)debug_info_data.GetDataStart();
uint32_t string_length = strlen(str) + 1;
- location.CopyOpcodeData(debug_info_data, string_offset, string_length);
+ location.CopyOpcodeData(module, debug_info_data, string_offset, string_length);
}
}
}
@@ -7340,21 +7356,21 @@ SymbolFileDWARF::ParseVariableDIE
has_explicit_location = true;
if (form_value.BlockData())
{
- const DataExtractor& debug_info_data = get_debug_info_data();
+ const DWARFDataExtractor& debug_info_data = get_debug_info_data();
uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
- location.CopyOpcodeData(get_debug_info_data(), block_offset, block_length);
+ location.CopyOpcodeData(module, get_debug_info_data(), block_offset, block_length);
}
else
{
- const DataExtractor& debug_loc_data = get_debug_loc_data();
+ const DWARFDataExtractor& debug_loc_data = get_debug_loc_data();
const dw_offset_t debug_loc_offset = form_value.Unsigned();
size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
if (loc_list_length > 0)
{
- location.CopyOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length);
+ location.CopyOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length);
assert (func_low_pc != LLDB_INVALID_ADDRESS);
location.SetLocationListSlide (func_low_pc - dwarf_cu->GetBaseAddress());
}
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index b6c6d94782db..55886572ada3 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -28,7 +28,6 @@
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/dwarf.h"
-#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Flags.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Symbol/ClangASTContext.h"
@@ -37,6 +36,7 @@
// Project includes
#include "DWARFDefines.h"
+#include "DWARFDataExtractor.h"
#include "HashedNameToDIE.h"
#include "NameToDIE.h"
#include "UniqueDWARFASTType.h"
@@ -199,18 +199,18 @@ public:
//virtual size_t GetCompUnitCount() = 0;
//virtual CompUnitSP GetCompUnitAtIndex(size_t cu_idx) = 0;
- const lldb_private::DataExtractor& get_debug_abbrev_data ();
- const lldb_private::DataExtractor& get_debug_aranges_data ();
- const lldb_private::DataExtractor& get_debug_frame_data ();
- const lldb_private::DataExtractor& get_debug_info_data ();
- const lldb_private::DataExtractor& get_debug_line_data ();
- const lldb_private::DataExtractor& get_debug_loc_data ();
- const lldb_private::DataExtractor& get_debug_ranges_data ();
- const lldb_private::DataExtractor& get_debug_str_data ();
- const lldb_private::DataExtractor& get_apple_names_data ();
- const lldb_private::DataExtractor& get_apple_types_data ();
- const lldb_private::DataExtractor& get_apple_namespaces_data ();
- const lldb_private::DataExtractor& get_apple_objc_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_abbrev_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_aranges_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_frame_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_info_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_line_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_loc_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_ranges_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_str_data ();
+ const lldb_private::DWARFDataExtractor& get_apple_names_data ();
+ const lldb_private::DWARFDataExtractor& get_apple_types_data ();
+ const lldb_private::DWARFDataExtractor& get_apple_namespaces_data ();
+ const lldb_private::DWARFDataExtractor& get_apple_objc_data ();
DWARFDebugAbbrev* DebugAbbrev();
@@ -222,10 +222,10 @@ public:
DWARFDebugRanges* DebugRanges();
const DWARFDebugRanges* DebugRanges() const;
- const lldb_private::DataExtractor&
+ const lldb_private::DWARFDataExtractor&
GetCachedSectionData (uint32_t got_flag,
lldb::SectionType sect_type,
- lldb_private::DataExtractor &data);
+ lldb_private::DWARFDataExtractor &data);
static bool
SupportedVersion(uint16_t version);
@@ -560,23 +560,23 @@ protected:
uint32_t type_mask,
TypeSet &type_set);
- lldb::ModuleWP m_debug_map_module_wp;
- SymbolFileDWARFDebugMap * m_debug_map_symfile;
- clang::TranslationUnitDecl * m_clang_tu_decl;
- lldb_private::Flags m_flags;
- lldb_private::DataExtractor m_dwarf_data;
- lldb_private::DataExtractor m_data_debug_abbrev;
- lldb_private::DataExtractor m_data_debug_aranges;
- lldb_private::DataExtractor m_data_debug_frame;
- lldb_private::DataExtractor m_data_debug_info;
- lldb_private::DataExtractor m_data_debug_line;
- lldb_private::DataExtractor m_data_debug_loc;
- lldb_private::DataExtractor m_data_debug_ranges;
- lldb_private::DataExtractor m_data_debug_str;
- lldb_private::DataExtractor m_data_apple_names;
- lldb_private::DataExtractor m_data_apple_types;
- lldb_private::DataExtractor m_data_apple_namespaces;
- lldb_private::DataExtractor m_data_apple_objc;
+ lldb::ModuleWP m_debug_map_module_wp;
+ SymbolFileDWARFDebugMap * m_debug_map_symfile;
+ clang::TranslationUnitDecl * m_clang_tu_decl;
+ lldb_private::Flags m_flags;
+ lldb_private::DWARFDataExtractor m_dwarf_data;
+ lldb_private::DWARFDataExtractor m_data_debug_abbrev;
+ lldb_private::DWARFDataExtractor m_data_debug_aranges;
+ lldb_private::DWARFDataExtractor m_data_debug_frame;
+ lldb_private::DWARFDataExtractor m_data_debug_info;
+ lldb_private::DWARFDataExtractor m_data_debug_line;
+ lldb_private::DWARFDataExtractor m_data_debug_loc;
+ lldb_private::DWARFDataExtractor m_data_debug_ranges;
+ lldb_private::DWARFDataExtractor m_data_debug_str;
+ lldb_private::DWARFDataExtractor m_data_apple_names;
+ lldb_private::DWARFDataExtractor m_data_apple_types;
+ lldb_private::DWARFDataExtractor m_data_apple_namespaces;
+ lldb_private::DWARFDataExtractor m_data_apple_objc;
// The unique pointer items below are generated on demand if and when someone accesses
// them through a non const version of this class.
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index a0430e3d52b6..856c42c2c9a6 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -847,7 +847,7 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext (const FileSpec& file_spec, uint32
if (GetFileSpecForSO (i, so_file_spec))
{
// Match the full path if the incoming file_spec has a directory (not just a basename)
- const bool full_match = file_spec.GetDirectory();
+ const bool full_match = (bool)file_spec.GetDirectory();
resolve = FileSpec::Equal (file_spec, so_file_spec, full_match);
}
}
diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index c93dea9b5d3c..8ddc1cd2ee84 100644
--- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -53,11 +53,13 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange&
ExecutionContext exe_ctx;
thread.CalculateExecutionContext(exe_ctx);
+ const bool prefer_file_cache = true;
DisassemblerSP disasm_sp (Disassembler::DisassembleRange (m_arch,
NULL,
NULL,
exe_ctx,
- range));
+ range,
+ prefer_file_cache));
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index d491683f6875..1768798f71d4 100644
--- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -597,16 +597,25 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
if (push_reg_p (machine_regno))
{
current_sp_bytes_offset_from_cfa += m_wordsize;
+ bool need_to_push_row = false;
+ // the PUSH instruction has moved the stack pointer - if the CFA is set in terms of the stack pointer,
+ // we need to add a new row of instructions.
+ if (row->GetCFARegister() == m_lldb_sp_regnum)
+ {
+ need_to_push_row = true;
+ row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
+ }
+ // record where non-volatile (callee-saved, spilled) registers are saved on the stack
if (nonvolatile_reg_p (machine_regno) && machine_regno_to_lldb_regno (machine_regno, lldb_regno))
{
- row->SetOffset (current_func_text_offset + insn_len);
- if (row->GetCFARegister() == m_lldb_sp_regnum)
- {
- row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
- }
+ need_to_push_row = true;
UnwindPlan::Row::RegisterLocation regloc;
regloc.SetAtCFAPlusOffset (-current_sp_bytes_offset_from_cfa);
row->SetRegisterInfo (lldb_regno, regloc);
+ }
+ if (need_to_push_row)
+ {
+ row->SetOffset (current_func_text_offset + insn_len);
unwind_plan.AppendRow (row);
// Allocate a new Row, populate it with the existing Row contents.
newrow = new UnwindPlan::Row;
diff --git a/source/Symbol/ClangASTImporter.cpp b/source/Symbol/ClangASTImporter.cpp
index 152949620450..afdca97ece27 100644
--- a/source/Symbol/ClangASTImporter.cpp
+++ b/source/Symbol/ClangASTImporter.cpp
@@ -716,3 +716,18 @@ ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to)
return clang::ASTImporter::Imported(from, to);
}
+
+clang::Decl *ClangASTImporter::Minion::GetOriginalDecl (clang::Decl *To)
+{
+ ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&To->getASTContext());
+
+ if (!to_context_md)
+ return NULL;
+
+ OriginMap::iterator iter = to_context_md->m_origins.find(To);
+
+ if (iter == to_context_md->m_origins.end())
+ return NULL;
+
+ return const_cast<clang::Decl*>(iter->second.decl);
+}
diff --git a/source/Symbol/ClangASTType.cpp b/source/Symbol/ClangASTType.cpp
index 2e7c0790fe57..0dfabcc931fb 100644
--- a/source/Symbol/ClangASTType.cpp
+++ b/source/Symbol/ClangASTType.cpp
@@ -288,6 +288,26 @@ ClangASTType::IsArrayType (ClangASTType *element_type_ptr,
return 0;
}
+bool
+ClangASTType::IsRuntimeGeneratedType () const
+{
+ if (!IsValid())
+ return false;
+
+ clang::DeclContext* decl_ctx = GetDeclContextForType();
+ if (!decl_ctx)
+ return false;
+
+ if (!llvm::isa<clang::ObjCInterfaceDecl>(decl_ctx))
+ return false;
+
+ clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
+
+ ClangASTMetadata* ast_metadata = ClangASTContext::GetMetadata(m_ast, result_iface_decl);
+ if (!ast_metadata)
+ return false;
+ return (ast_metadata->GetISAPtr() != 0);
+}
bool
ClangASTType::IsCharType () const
@@ -385,6 +405,34 @@ ClangASTType::IsFunctionType (bool *is_variadic_ptr) const
return false;
}
+size_t
+ClangASTType::GetNumberOfFunctionArguments () const
+{
+ if (IsValid())
+ {
+ QualType qual_type (GetCanonicalQualType());
+ const FunctionProtoType* func = dyn_cast<FunctionProtoType>(qual_type.getTypePtr());
+ if (func)
+ return func->getNumArgs();
+ }
+ return 0;
+}
+
+ClangASTType
+ClangASTType::GetFunctionArgumentAtIndex (const size_t index)
+{
+ if (IsValid())
+ {
+ QualType qual_type (GetCanonicalQualType());
+ const FunctionProtoType* func = dyn_cast<FunctionProtoType>(qual_type.getTypePtr());
+ if (func)
+ {
+ if (index < func->getNumArgs())
+ return ClangASTType(m_ast, func->getArgType(index).getAsOpaquePtr());
+ }
+ }
+ return ClangASTType();
+}
bool
ClangASTType::IsFunctionPointerType () const
@@ -1065,14 +1113,14 @@ ClangASTType::GetConstTypeName () const
{
if (IsValid())
{
- std::string type_name (GetTypeName());
- if (!type_name.empty())
- return ConstString (type_name.c_str());
+ ConstString type_name (GetTypeName());
+ if (type_name)
+ return type_name;
}
return ConstString("<invalid>");
}
-std::string
+ConstString
ClangASTType::GetTypeName () const
{
std::string type_name;
@@ -1093,7 +1141,7 @@ ClangASTType::GetTypeName () const
type_name = qual_type.getAsString(printing_policy);
}
}
- return type_name;
+ return ConstString(type_name);
}
@@ -1428,6 +1476,9 @@ ClangASTType::GetTypeClass () const
case clang::Type::Decltype: break;
case clang::Type::TemplateSpecialization: break;
case clang::Type::Atomic: break;
+
+ // pointer type decayed from an array or function type.
+ case clang::Type::Decayed: break;
}
// We don't know hot to display this type...
return lldb::eTypeClassOther;
@@ -1865,7 +1916,10 @@ ClangASTType::GetEncoding (uint64_t &count) const
case clang::Type::TemplateSpecialization:
case clang::Type::Atomic:
break;
-
+
+ // pointer type decayed from an array or function type.
+ case clang::Type::Decayed:
+ break;
}
count = 0;
return lldb::eEncodingInvalid;
@@ -1994,6 +2048,10 @@ ClangASTType::GetFormat () const
case clang::Type::TemplateSpecialization:
case clang::Type::Atomic:
break;
+
+ // pointer type decayed from an array or function type.
+ case clang::Type::Decayed:
+ break;
}
// We don't know hot to display this type...
return lldb::eFormatBytes;
@@ -2271,26 +2329,29 @@ ClangASTType::GetNumDirectBaseClasses () const
break;
case clang::Type::ObjCObjectPointer:
+ count = GetPointeeType().GetNumDirectBaseClasses();
+ break;
+
+ case clang::Type::ObjCObject:
if (GetCompleteType())
{
- const ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
+ const ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
+ ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+
if (class_interface_decl && class_interface_decl->getSuperClass())
count = 1;
}
}
break;
-
- case clang::Type::ObjCObject:
case clang::Type::ObjCInterface:
if (GetCompleteType())
{
- const ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
- if (objc_class_type)
+ const ObjCInterfaceType *objc_interface_type = qual_type->getAs<ObjCInterfaceType>();
+ if (objc_interface_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface();
if (class_interface_decl && class_interface_decl->getSuperClass())
count = 1;
@@ -2472,12 +2533,16 @@ ClangASTType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) c
break;
case clang::Type::ObjCObjectPointer:
+ return GetPointeeType().GetDirectBaseClassAtIndex(idx,bit_offset_ptr);
+
+ case clang::Type::ObjCObject:
if (idx == 0 && GetCompleteType())
{
- const ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
+ const ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
if (objc_class_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
+ ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+
if (class_interface_decl)
{
ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
@@ -2491,15 +2556,13 @@ ClangASTType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) c
}
}
break;
-
- case clang::Type::ObjCObject:
case clang::Type::ObjCInterface:
if (idx == 0 && GetCompleteType())
{
- const ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
- if (objc_class_type)
+ const ObjCObjectType *objc_interface_type = qual_type->getAs<ObjCInterfaceType>();
+ if (objc_interface_type)
{
- ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface();
if (class_interface_decl)
{
@@ -2977,7 +3040,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
// Base classes should be a multiple of 8 bits in size
child_byte_offset = bit_offset/8;
ClangASTType base_class_clang_type(m_ast, base_class->getType());
- child_name = base_class_clang_type.GetTypeName();
+ child_name = base_class_clang_type.GetTypeName().AsCString("");
uint64_t base_class_clang_type_bit_size = base_class_clang_type.GetBitSize();
// Base classes bit sizes should be a multiple of 8 bits in size
@@ -3507,7 +3570,17 @@ ClangASTType::GetIndexOfChildMemberWithName (const char *name,
field != field_end;
++field, ++child_idx)
{
- if (field->getName().equals (name_sref))
+ llvm::StringRef field_name = field->getName();
+ if (field_name.empty())
+ {
+ ClangASTType field_type(m_ast,field->getType());
+ child_indexes.push_back(child_idx);
+ if (field_type.GetIndexOfChildMemberWithName(name, omit_empty_base_classes, child_indexes))
+ return child_indexes.size();
+ child_indexes.pop_back();
+
+ }
+ else if (field_name.equals (name_sref))
{
// We have to add on the number of base classes to this index!
child_indexes.push_back (child_idx + ClangASTContext::GetNumBaseClasses (cxx_record_decl, omit_empty_base_classes));
@@ -3767,7 +3840,7 @@ ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_cl
continue;
ClangASTType base_class_clang_type (m_ast, base_class->getType());
- std::string base_class_type_name (base_class_clang_type.GetTypeName());
+ std::string base_class_type_name (base_class_clang_type.GetTypeName().AsCString(""));
if (base_class_type_name.compare (name) == 0)
return child_idx;
++child_idx;
@@ -5165,6 +5238,9 @@ ClangASTType::GetDeclContextForType () const
case clang::Type::InjectedClassName: break;
case clang::Type::DependentName: break;
case clang::Type::Atomic: break;
+
+ // pointer type decayed from an array or function type.
+ case clang::Type::Decayed: break;
}
// No DeclContext in this type...
return NULL;
diff --git a/source/Symbol/CompileUnit.cpp b/source/Symbol/CompileUnit.cpp
index 751b09ec5a6b..62ae1cc1cbe0 100644
--- a/source/Symbol/CompileUnit.cpp
+++ b/source/Symbol/CompileUnit.cpp
@@ -324,7 +324,7 @@ CompileUnit::ResolveSymbolContext
// "file_spec" has an empty directory, then only compare the basenames
// when finding file indexes
std::vector<uint32_t> file_indexes;
- const bool full_match = file_spec.GetDirectory();
+ const bool full_match = (bool)file_spec.GetDirectory();
bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, full_match);
// If we are not looking for inlined functions and our file spec doesn't
diff --git a/source/Symbol/DWARFCallFrameInfo.cpp b/source/Symbol/DWARFCallFrameInfo.cpp
index e8f99a980116..d3d962896694 100644
--- a/source/Symbol/DWARFCallFrameInfo.cpp
+++ b/source/Symbol/DWARFCallFrameInfo.cpp
@@ -341,7 +341,7 @@ DWARFCallFrameInfo::GetFDEIndex ()
dw_offset_t next_entry = current_entry + len + 4;
dw_offset_t cie_id = m_cfi_data.GetU32 (&offset);
- if (cie_id == 0 || cie_id == UINT32_MAX)
+ if (cie_id == 0 || cie_id == UINT32_MAX || len == 0)
{
m_cie_map[current_entry] = ParseCIE (current_entry);
offset = next_entry;
@@ -444,6 +444,8 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
unwind_plan.SetRegisterKind (m_reg_kind);
unwind_plan.SetReturnAddressRegister (cie->return_addr_reg_num);
+ std::vector<UnwindPlan::RowSP> stack;
+
UnwindPlan::Row::RegisterLocation reg_location;
while (m_cfi_data.ValidOffset(offset) && offset < end_offset)
{
@@ -629,7 +631,7 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
// the stack and place them in the current row. (This operation is
// useful for compilers that move epilogue code into the body of a
// function.)
- unwind_plan.AppendRow (row);
+ stack.push_back (row);
UnwindPlan::Row *newrow = new UnwindPlan::Row;
*newrow = *row.get();
row.reset (newrow);
@@ -645,7 +647,8 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
// useful for compilers that move epilogue code into the body of a
// function.)
{
- row = unwind_plan.GetRowAtIndex(unwind_plan.GetRowCount() - 1);
+ row = stack.back ();
+ stack.pop_back ();
}
break;
diff --git a/source/Symbol/FuncUnwinders.cpp b/source/Symbol/FuncUnwinders.cpp
index 3de06179ee07..68b05ade4bd0 100644
--- a/source/Symbol/FuncUnwinders.cpp
+++ b/source/Symbol/FuncUnwinders.cpp
@@ -114,9 +114,12 @@ FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread)
if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == NULL)
{
m_tried_unwind_at_non_call_site = true;
- 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))
- m_unwind_plan_non_call_site_sp.reset();
+ if (m_assembly_profiler)
+ {
+ 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))
+ m_unwind_plan_non_call_site_sp.reset();
+ }
}
return m_unwind_plan_non_call_site_sp;
}
@@ -140,9 +143,12 @@ FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == NULL)
{
m_tried_unwind_fast = true;
- m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
- if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp))
- m_unwind_plan_fast_sp.reset();
+ if (m_assembly_profiler)
+ {
+ m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+ if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp))
+ m_unwind_plan_fast_sp.reset();
+ }
}
return m_unwind_plan_fast_sp;
}
@@ -216,7 +222,7 @@ FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread)
}
}
- return m_unwind_plan_arch_default_sp;
+ return m_unwind_plan_arch_default_at_func_entry_sp;
}
@@ -226,7 +232,8 @@ 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);
- m_assembly_profiler->FirstNonPrologueInsn (m_range, exe_ctx, m_first_non_prologue_insn);
+ if (m_assembly_profiler)
+ m_assembly_profiler->FirstNonPrologueInsn (m_range, exe_ctx, m_first_non_prologue_insn);
return m_first_non_prologue_insn;
}
diff --git a/source/Symbol/LineEntry.cpp b/source/Symbol/LineEntry.cpp
index 10dc552ea01a..08a2392e1136 100644
--- a/source/Symbol/LineEntry.cpp
+++ b/source/Symbol/LineEntry.cpp
@@ -17,7 +17,7 @@ using namespace lldb_private;
LineEntry::LineEntry() :
range(),
file(),
- line(0),
+ line(LLDB_INVALID_LINE_NUMBER),
column(0),
is_start_of_statement(0),
is_start_of_basic_block(0),
@@ -58,7 +58,7 @@ LineEntry::Clear()
{
range.Clear();
file.Clear();
- line = 0;
+ line = LLDB_INVALID_LINE_NUMBER;
column = 0;
is_start_of_statement = 0;
is_start_of_basic_block = 0;
@@ -71,7 +71,7 @@ LineEntry::Clear()
bool
LineEntry::IsValid() const
{
- return range.GetBaseAddress().IsValid() && line != 0;
+ return range.GetBaseAddress().IsValid() && line != LLDB_INVALID_LINE_NUMBER;
}
bool
diff --git a/source/Symbol/ObjectFile.cpp b/source/Symbol/ObjectFile.cpp
index 0c6159122cfb..ec69c9dd1e15 100644
--- a/source/Symbol/ObjectFile.cpp
+++ b/source/Symbol/ObjectFile.cpp
@@ -423,6 +423,7 @@ ObjectFile::GetAddressClass (addr_t file_addr)
case eSymbolTypeObjCClass: return eAddressClassRuntime;
case eSymbolTypeObjCMetaClass: return eAddressClassRuntime;
case eSymbolTypeObjCIVar: return eAddressClassRuntime;
+ case eSymbolTypeReExported: return eAddressClassRuntime;
}
}
}
@@ -459,7 +460,8 @@ size_t
ObjectFile::CopyData (off_t offset, size_t length, void *dst) const
{
// The entire file has already been mmap'ed into m_data, so just copy from there
- return m_data.CopyByteOrderedData (offset, length, dst, length, lldb::endian::InlHostByteOrder());
+ // Note that the data remains in target byte order.
+ return m_data.CopyData (offset, length, dst);
}
@@ -501,7 +503,7 @@ ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void
uint64_t section_dst_len = dst_len;
if (section_dst_len > section_bytes_left)
section_dst_len = section_bytes_left;
- bzero(dst, section_dst_len);
+ memset(dst, 0, section_dst_len);
return section_dst_len;
}
}
diff --git a/source/Symbol/Symbol.cpp b/source/Symbol/Symbol.cpp
index 7f3543c3b232..a881b6f31012 100644
--- a/source/Symbol/Symbol.cpp
+++ b/source/Symbol/Symbol.cpp
@@ -10,6 +10,7 @@
#include "lldb/Symbol/Symbol.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -176,6 +177,66 @@ Symbol::ValueIsAddress() const
return m_addr_range.GetBaseAddress().GetSection().get() != NULL;
}
+ConstString
+Symbol::GetReExportedSymbolName() const
+{
+ if (m_type == eSymbolTypeReExported)
+ {
+ // For eSymbolTypeReExported, the "const char *" from a ConstString
+ // is used as the offset in the address range base address. We can
+ // then make this back into a string that is the re-exported name.
+ intptr_t str_ptr = m_addr_range.GetBaseAddress().GetOffset();
+ if (str_ptr != 0)
+ return ConstString((const char *)str_ptr);
+ else
+ return GetName();
+ }
+ return ConstString();
+}
+
+FileSpec
+Symbol::GetReExportedSymbolSharedLibrary() const
+{
+ if (m_type == eSymbolTypeReExported)
+ {
+ // For eSymbolTypeReExported, the "const char *" from a ConstString
+ // is used as the offset in the address range base address. We can
+ // then make this back into a string that is the re-exported name.
+ intptr_t str_ptr = m_addr_range.GetByteSize();
+ if (str_ptr != 0)
+ return FileSpec((const char *)str_ptr, false);
+ }
+ return FileSpec();
+}
+
+bool
+Symbol::SetReExportedSymbolName(const ConstString &name)
+{
+ if (m_type == eSymbolTypeReExported)
+ {
+ // For eSymbolTypeReExported, the "const char *" from a ConstString
+ // is used as the offset in the address range base address.
+ m_addr_range.GetBaseAddress().SetOffset((intptr_t)name.GetCString());
+ return true;
+ }
+ return false;
+
+}
+
+bool
+Symbol::SetReExportedSymbolSharedLibrary(const FileSpec &fspec)
+{
+ if (m_type == eSymbolTypeReExported)
+ {
+ // For eSymbolTypeReExported, the "const char *" from a ConstString
+ // is used as the offset in the address range base address.
+ m_addr_range.SetByteSize((intptr_t)ConstString(fspec.GetPath().c_str()).GetCString());
+ return true;
+ }
+ return false;
+
+}
+
uint32_t
Symbol::GetSiblingIndex() const
{
@@ -267,6 +328,19 @@ Symbol::Dump(Stream *s, Target *target, uint32_t index) const
m_flags,
m_mangled.GetName().AsCString(""));
}
+ else if (m_type == eSymbolTypeReExported)
+ {
+ s->Printf (" 0x%8.8x %s",
+ m_flags,
+ m_mangled.GetName().AsCString(""));
+
+ ConstString reexport_name = GetReExportedSymbolName();
+ intptr_t shlib = m_addr_range.GetByteSize();
+ if (shlib)
+ s->Printf(" -> %s`%s\n", (const char *)shlib, reexport_name.GetCString());
+ else
+ s->Printf(" -> %s\n", reexport_name.GetCString());
+ }
else
{
const char *format = m_size_is_sibling ?
@@ -380,6 +454,7 @@ Symbol::GetTypeAsString() const
ENUM_TO_CSTRING(Invalid);
ENUM_TO_CSTRING(Absolute);
ENUM_TO_CSTRING(Code);
+ ENUM_TO_CSTRING(Resolver);
ENUM_TO_CSTRING(Data);
ENUM_TO_CSTRING(Trampoline);
ENUM_TO_CSTRING(Runtime);
@@ -404,6 +479,7 @@ Symbol::GetTypeAsString() const
ENUM_TO_CSTRING(ObjCClass);
ENUM_TO_CSTRING(ObjCMetaClass);
ENUM_TO_CSTRING(ObjCIVar);
+ ENUM_TO_CSTRING(ReExported);
default:
break;
}
@@ -460,3 +536,47 @@ Symbol::GetByteSize () const
return m_addr_range.GetByteSize();
}
+Symbol *
+Symbol::ResolveReExportedSymbol (Target &target)
+{
+ ConstString reexport_name (GetReExportedSymbolName());
+ if (reexport_name)
+ {
+ 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)
+ {
+ // 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)
+ {
+ 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)
+ {
+ lldb_private::SymbolContext sc;
+ if (sc_list.GetContextAtIndex(i, sc))
+ {
+ if (sc.symbol->IsExternal())
+ return sc.symbol;
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+}
diff --git a/source/Symbol/SymbolContext.cpp b/source/Symbol/SymbolContext.cpp
index ac91161f7d6f..f1e581f71613 100644
--- a/source/Symbol/SymbolContext.cpp
+++ b/source/Symbol/SymbolContext.cpp
@@ -910,15 +910,15 @@ SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level)
s->Printf ("File: %s", path_str);
if (m_type == eLineStartSpecified)
{
- s->Printf (" from line %lu", m_start_line);
+ s->Printf (" from line %zu", m_start_line);
if (m_type == eLineEndSpecified)
- s->Printf ("to line %lu", m_end_line);
+ s->Printf ("to line %zu", m_end_line);
else
s->Printf ("to end");
}
else if (m_type == eLineEndSpecified)
{
- s->Printf (" from start to line %ld", m_end_line);
+ s->Printf (" from start to line %zu", 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 %lu", m_start_line);
+ s->Printf ("From line %zu", m_start_line);
if (m_type == eLineEndSpecified)
- s->Printf ("to line %lu", m_end_line);
+ s->Printf ("to line %zu", m_end_line);
else
s->Printf ("to end");
s->Printf (".\n");
}
else if (m_type == eLineEndSpecified)
{
- s->Printf ("From start to line %ld.\n", m_end_line);
+ s->Printf ("From start to line %zu.\n", m_end_line);
}
if (m_type == eFunctionSpecified)
diff --git a/source/Symbol/Symtab.cpp b/source/Symbol/Symtab.cpp
index 27af6988aa9d..430fc1789202 100644
--- a/source/Symbol/Symtab.cpp
+++ b/source/Symbol/Symtab.cpp
@@ -90,14 +90,14 @@ Symtab::Dump (Stream *s, Target *target, SortOrder sort_order)
object_name = m_objfile->GetModule()->GetObjectName().GetCString();
if (file_spec)
- s->Printf("Symtab, file = %s%s%s%s, num_symbols = %lu",
+ s->Printf("Symtab, file = %s%s%s%s, num_symbols = %zu",
file_spec.GetPath().c_str(),
object_name ? "(" : "",
object_name ? object_name : "",
object_name ? ")" : "",
m_symbols.size());
else
- s->Printf("Symtab, num_symbols = %lu", m_symbols.size());
+ s->Printf("Symtab, num_symbols = %zu", m_symbols.size());
if (!m_symbols.empty())
{
@@ -166,7 +166,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 %lu symbol indexes (%lu symbols total):\n", indexes.size(), m_symbols.size());
+ s->Printf("Symtab %zu symbol indexes (%zu symbols total):\n", indexes.size(), m_symbols.size());
s->IndentMore();
if (!indexes.empty())
@@ -682,7 +682,7 @@ Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, Symb
if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
++pos;
else
- indexes.erase(pos);
+ pos = indexes.erase(pos);
}
}
return indexes.size();
@@ -701,7 +701,7 @@ Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, Symb
if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
++pos;
else
- indexes.erase(pos);
+ pos = indexes.erase(pos);
}
}
return indexes.size();
@@ -1135,6 +1135,7 @@ Symtab::FindFunctionSymbols (const ConstString &name,
{
case eSymbolTypeCode:
case eSymbolTypeResolver:
+ case eSymbolTypeReExported:
symbol_indexes.push_back(temp_symbol_indexes[i]);
break;
default:
diff --git a/source/Symbol/Type.cpp b/source/Symbol/Type.cpp
index 0af2359e1dad..32a1d474053f 100644
--- a/source/Symbol/Type.cpp
+++ b/source/Symbol/Type.cpp
@@ -798,12 +798,12 @@ Type::GetTypeScopeAndBasename (const char* &name_cstr,
-TypeAndOrName::TypeAndOrName () : m_type_sp(), m_type_name()
+TypeAndOrName::TypeAndOrName () : m_type_pair(), m_type_name()
{
}
-TypeAndOrName::TypeAndOrName (TypeSP &in_type_sp) : m_type_sp(in_type_sp)
+TypeAndOrName::TypeAndOrName (TypeSP &in_type_sp) : m_type_pair(in_type_sp)
{
if (in_type_sp)
m_type_name = in_type_sp->GetName();
@@ -813,7 +813,7 @@ TypeAndOrName::TypeAndOrName (const char *in_type_str) : m_type_name(in_type_str
{
}
-TypeAndOrName::TypeAndOrName (const TypeAndOrName &rhs) : m_type_sp (rhs.m_type_sp), m_type_name (rhs.m_type_name)
+TypeAndOrName::TypeAndOrName (const TypeAndOrName &rhs) : m_type_pair (rhs.m_type_pair), m_type_name (rhs.m_type_name)
{
}
@@ -828,7 +828,7 @@ TypeAndOrName::operator= (const TypeAndOrName &rhs)
if (this != &rhs)
{
m_type_name = rhs.m_type_name;
- m_type_sp = rhs.m_type_sp;
+ m_type_pair = rhs.m_type_pair;
}
return *this;
}
@@ -836,7 +836,7 @@ TypeAndOrName::operator= (const TypeAndOrName &rhs)
bool
TypeAndOrName::operator==(const TypeAndOrName &other) const
{
- if (m_type_sp != other.m_type_sp)
+ if (m_type_pair != other.m_type_pair)
return false;
if (m_type_name != other.m_type_name)
return false;
@@ -846,7 +846,7 @@ TypeAndOrName::operator==(const TypeAndOrName &other) const
bool
TypeAndOrName::operator!=(const TypeAndOrName &other) const
{
- if (m_type_sp != other.m_type_sp)
+ if (m_type_pair != other.m_type_pair)
return true;
if (m_type_name != other.m_type_name)
return true;
@@ -855,11 +855,12 @@ TypeAndOrName::operator!=(const TypeAndOrName &other) const
ConstString
TypeAndOrName::GetName () const
-{
- if (m_type_sp)
- return m_type_sp->GetName();
- else
+{
+ if (m_type_name)
return m_type_name;
+ if (m_type_pair)
+ return m_type_pair.GetName();
+ return ConstString("<invalid>");
}
void
@@ -877,15 +878,23 @@ TypeAndOrName::SetName (const char *type_name_cstr)
void
TypeAndOrName::SetTypeSP (lldb::TypeSP type_sp)
{
- m_type_sp = type_sp;
- if (type_sp)
- m_type_name = type_sp->GetName();
+ m_type_pair.SetType(type_sp);
+ if (m_type_pair)
+ m_type_name = m_type_pair.GetName();
+}
+
+void
+TypeAndOrName::SetClangASTType (ClangASTType clang_type)
+{
+ m_type_pair.SetType(clang_type);
+ if (m_type_pair)
+ m_type_name = m_type_pair.GetName();
}
bool
-TypeAndOrName::IsEmpty()
+TypeAndOrName::IsEmpty() const
{
- if (m_type_name || m_type_sp)
+ if ((bool)m_type_name || (bool)m_type_pair)
return false;
else
return true;
@@ -895,96 +904,247 @@ void
TypeAndOrName::Clear ()
{
m_type_name.Clear();
- m_type_sp.reset();
+ m_type_pair.Clear();
}
bool
-TypeAndOrName::HasName ()
+TypeAndOrName::HasName () const
{
return (bool)m_type_name;
}
bool
-TypeAndOrName::HasTypeSP ()
+TypeAndOrName::HasTypeSP () const
+{
+ return m_type_pair.GetTypeSP().get() != nullptr;
+}
+
+bool
+TypeAndOrName::HasClangASTType () const
+{
+ return m_type_pair.GetClangASTType().IsValid();
+}
+
+
+TypeImpl::TypeImpl() :
+m_static_type(),
+m_dynamic_type()
{
- return m_type_sp.get() != NULL;
}
-TypeImpl::TypeImpl(const lldb_private::ClangASTType& clang_ast_type) :
- m_clang_ast_type(clang_ast_type),
- m_type_sp()
+TypeImpl::TypeImpl(const TypeImpl& rhs) :
+m_static_type(rhs.m_static_type),
+m_dynamic_type(rhs.m_dynamic_type)
{
}
-TypeImpl::TypeImpl(const lldb::TypeSP& type) :
- m_clang_ast_type(type->GetClangForwardType()),
- m_type_sp(type)
+TypeImpl::TypeImpl (lldb::TypeSP type_sp) :
+m_static_type(type_sp),
+m_dynamic_type()
+{
+}
+
+TypeImpl::TypeImpl (ClangASTType clang_type) :
+m_static_type(clang_type),
+m_dynamic_type()
+{
+}
+
+TypeImpl::TypeImpl (lldb::TypeSP type_sp, ClangASTType dynamic) :
+m_static_type (type_sp),
+m_dynamic_type(dynamic)
+{
+}
+
+TypeImpl::TypeImpl (ClangASTType clang_type, ClangASTType dynamic) :
+m_static_type (clang_type),
+m_dynamic_type(dynamic)
+{
+}
+
+TypeImpl::TypeImpl (TypePair pair, ClangASTType dynamic) :
+m_static_type (pair),
+m_dynamic_type(dynamic)
{
}
void
-TypeImpl::SetType (const lldb::TypeSP &type_sp)
+TypeImpl::SetType (lldb::TypeSP type_sp)
{
- if (type_sp)
- {
- m_clang_ast_type = type_sp->GetClangForwardType();
- m_type_sp = type_sp;
- }
- else
- {
- m_clang_ast_type.Clear();
- m_type_sp.reset();
- }
+ m_static_type.SetType(type_sp);
+}
+
+void
+TypeImpl::SetType (ClangASTType clang_type)
+{
+ m_static_type.SetType (clang_type);
+}
+
+void
+TypeImpl::SetType (lldb::TypeSP type_sp, ClangASTType dynamic)
+{
+ m_static_type.SetType (type_sp);
+ m_dynamic_type = dynamic;
+}
+
+void
+TypeImpl::SetType (ClangASTType clang_type, ClangASTType dynamic)
+{
+ m_static_type.SetType (clang_type);
+ m_dynamic_type = dynamic;
+}
+
+void
+TypeImpl::SetType (TypePair pair, ClangASTType dynamic)
+{
+ m_static_type = pair;
+ m_dynamic_type = dynamic;
}
TypeImpl&
TypeImpl::operator = (const TypeImpl& rhs)
{
- if (*this != rhs)
+ if (rhs != *this)
{
- m_clang_ast_type = rhs.m_clang_ast_type;
- m_type_sp = rhs.m_type_sp;
+ m_static_type = rhs.m_static_type;
+ m_dynamic_type = rhs.m_dynamic_type;
}
return *this;
}
-clang::ASTContext*
-TypeImpl::GetASTContext()
+bool
+TypeImpl::operator == (const TypeImpl& rhs) const
{
- if (!IsValid())
- return NULL;
-
- return m_clang_ast_type.GetASTContext();
+ return m_static_type == rhs.m_static_type &&
+ m_dynamic_type == rhs.m_dynamic_type;
}
-lldb::clang_type_t
-TypeImpl::GetOpaqueQualType()
+bool
+TypeImpl::operator != (const TypeImpl& rhs) const
{
- if (!IsValid())
- return NULL;
-
- return m_clang_ast_type.GetOpaqueQualType();
+ return m_static_type != rhs.m_static_type ||
+ m_dynamic_type != rhs.m_dynamic_type;
}
bool
-TypeImpl::GetDescription (lldb_private::Stream &strm,
- lldb::DescriptionLevel description_level)
+TypeImpl::IsValid() const
+{
+ // just a name is not valid
+ return m_static_type.IsValid() || m_dynamic_type.IsValid();
+}
+
+TypeImpl::operator bool () const
+{
+ return IsValid();
+}
+
+void
+TypeImpl::Clear()
+{
+ m_static_type.Clear();
+ m_dynamic_type.Clear();
+}
+
+ConstString
+TypeImpl::GetName () const
{
- if (m_clang_ast_type.IsValid())
+ if (m_dynamic_type)
+ return m_dynamic_type.GetTypeName();
+ return m_static_type.GetName ();
+}
+
+TypeImpl
+TypeImpl::GetPointerType () const
+{
+ if (m_dynamic_type.IsValid())
{
- m_clang_ast_type.DumpTypeDescription (&strm);
+ return TypeImpl(m_static_type, m_dynamic_type.GetPointerType());
}
- else
+ return TypeImpl(m_static_type.GetPointerType());
+}
+
+TypeImpl
+TypeImpl::GetPointeeType () const
+{
+ if (m_dynamic_type.IsValid())
{
- strm.PutCString ("No value");
+ return TypeImpl(m_static_type, m_dynamic_type.GetPointeeType());
}
- return true;
+ return TypeImpl(m_static_type.GetPointeeType());
}
-ConstString
-TypeImpl::GetName ()
+TypeImpl
+TypeImpl::GetReferenceType () const
{
- if (m_clang_ast_type.IsValid())
- return m_clang_ast_type.GetConstTypeName();
- return ConstString();
+ if (m_dynamic_type.IsValid())
+ {
+ return TypeImpl(m_static_type, m_dynamic_type.GetLValueReferenceType());
+ }
+ return TypeImpl(m_static_type.GetReferenceType());
+}
+
+TypeImpl
+TypeImpl::GetDereferencedType () const
+{
+ if (m_dynamic_type.IsValid())
+ {
+ return TypeImpl(m_static_type, m_dynamic_type.GetNonReferenceType());
+ }
+ return TypeImpl(m_static_type.GetDereferencedType());
+}
+
+TypeImpl
+TypeImpl::GetUnqualifiedType() const
+{
+ if (m_dynamic_type.IsValid())
+ {
+ return TypeImpl(m_static_type, m_dynamic_type.GetFullyUnqualifiedType());
+ }
+ return TypeImpl(m_static_type.GetUnqualifiedType());
+}
+
+TypeImpl
+TypeImpl::GetCanonicalType() const
+{
+ if (m_dynamic_type.IsValid())
+ {
+ return TypeImpl(m_static_type, m_dynamic_type.GetCanonicalType());
+ }
+ return TypeImpl(m_static_type.GetCanonicalType());
+}
+
+ClangASTType
+TypeImpl::GetClangASTType (bool prefer_dynamic)
+{
+ if (prefer_dynamic)
+ {
+ if (m_dynamic_type.IsValid())
+ return m_dynamic_type;
+ }
+ return m_static_type.GetClangASTType();
+}
+
+clang::ASTContext *
+TypeImpl::GetClangASTContext (bool prefer_dynamic)
+{
+ if (prefer_dynamic)
+ {
+ if (m_dynamic_type.IsValid())
+ return m_dynamic_type.GetASTContext();
+ }
+ return m_static_type.GetClangASTContext();
+}
+
+bool
+TypeImpl::GetDescription (lldb_private::Stream &strm,
+ lldb::DescriptionLevel description_level)
+{
+ if (m_dynamic_type.IsValid())
+ {
+ strm.Printf("Dynamic:\n");
+ m_dynamic_type.DumpTypeDescription(&strm);
+ strm.Printf("\nStatic:\n");
+ }
+ m_static_type.GetClangASTType().DumpTypeDescription(&strm);
+ return true;
}
diff --git a/source/Symbol/UnwindTable.cpp b/source/Symbol/UnwindTable.cpp
index c77628bf7dd8..33eb4d6c092b 100644
--- a/source/Symbol/UnwindTable.cpp
+++ b/source/Symbol/UnwindTable.cpp
@@ -102,7 +102,7 @@ UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolConte
FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range));
m_unwinds.insert (insert_pos, std::make_pair(range.GetBaseAddress().GetFileAddress(), func_unwinder_sp));
-// StreamFile s(stdout);
+// StreamFile s(stdout, false);
// Dump (s);
return func_unwinder_sp;
}
diff --git a/source/Symbol/Variable.cpp b/source/Symbol/Variable.cpp
index 36439b561626..7276e0a4a1a2 100644
--- a/source/Symbol/Variable.cpp
+++ b/source/Symbol/Variable.cpp
@@ -684,11 +684,14 @@ PrivateAutoComplete (StackFrame *frame,
VariableList *variable_list = frame->GetVariableList(get_file_globals);
- const size_t num_variables = variable_list->GetSize();
- for (size_t i=0; i<num_variables; ++i)
+ if (variable_list)
{
- Variable *variable = variable_list->GetVariableAtIndex(i).get();
- matches.AppendString (variable->GetName().AsCString());
+ const size_t num_variables = variable_list->GetSize();
+ for (size_t i=0; i<num_variables; ++i)
+ {
+ Variable *variable = variable_list->GetVariableAtIndex(i).get();
+ matches.AppendString (variable->GetName().AsCString());
+ }
}
}
}
diff --git a/source/Target/ExecutionContext.cpp b/source/Target/ExecutionContext.cpp
index 8b5731e80280..7a8b60189bc8 100644
--- a/source/Target/ExecutionContext.cpp
+++ b/source/Target/ExecutionContext.cpp
@@ -241,7 +241,15 @@ ExecutionContext::GetAddressByteSize() const
return sizeof(void *);
}
-
+lldb::ByteOrder
+ExecutionContext::GetByteOrder() const
+{
+ if (m_target_sp && m_target_sp->GetArchitecture().IsValid())
+ m_target_sp->GetArchitecture().GetByteOrder();
+ if (m_process_sp)
+ m_process_sp->GetByteOrder();
+ return lldb::endian::InlHostByteOrder();
+}
RegisterContext *
ExecutionContext::GetRegisterContext () const
diff --git a/source/Target/LanguageRuntime.cpp b/source/Target/LanguageRuntime.cpp
index d2f586ac82fb..2fdc2539d08b 100644
--- a/source/Target/LanguageRuntime.cpp
+++ b/source/Target/LanguageRuntime.cpp
@@ -268,8 +268,8 @@ LanguageRuntime::CreateExceptionBreakpoint (Target &target,
{
BreakpointResolverSP resolver_sp(new ExceptionBreakpointResolver(language, catch_bp, throw_bp));
SearchFilterSP filter_sp(new ExceptionSearchFilter(target.shared_from_this(), language));
-
- BreakpointSP exc_breakpt_sp (target.CreateBreakpoint (filter_sp, resolver_sp, is_internal));
+ bool hardware = false;
+ BreakpointSP exc_breakpt_sp (target.CreateBreakpoint (filter_sp, resolver_sp, is_internal, hardware));
if (is_internal)
exc_breakpt_sp->SetBreakpointKind("exception");
diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp
index e6d3bc7a55d0..75d94bd91ce3 100644
--- a/source/Target/Platform.cpp
+++ b/source/Target/Platform.cpp
@@ -22,6 +22,7 @@
#include "lldb/Host/Host.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/Utils.h"
using namespace lldb;
using namespace lldb_private;
@@ -247,7 +248,13 @@ Platform::Platform (bool is_host) :
m_uid_map(),
m_gid_map(),
m_max_uid_name_len (0),
- m_max_gid_name_len (0)
+ m_max_gid_name_len (0),
+ m_supports_rsync (false),
+ m_rsync_opts (),
+ m_rsync_prefix (),
+ m_supports_ssh (false),
+ m_ssh_opts (),
+ m_ignores_remote_hostname (false)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
@@ -311,6 +318,14 @@ Platform::GetStatus (Stream &strm)
strm.Printf(" Hostname: %s\n", GetHostname());
strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
}
+
+ if (!IsConnected())
+ return;
+
+ std::string specific_info(GetPlatformSpecificConnectionInformation());
+
+ if (specific_info.empty() == false)
+ strm.Printf("Platform-specific connection: %s\n", specific_info.c_str());
}
@@ -649,10 +664,12 @@ Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
const bool is_localhost = true;
const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);
const bool first_arg_is_full_shell_command = false;
+ uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info);
if (!launch_info.ConvertArgumentsForLaunchingInShell (error,
is_localhost,
will_debug,
- first_arg_is_full_shell_command))
+ first_arg_is_full_shell_command,
+ num_resumes))
return error;
}
@@ -760,9 +777,161 @@ Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match,
if (compatible_arch_ptr)
compatible_arch_ptr->Clear();
return false;
+}
+
+uint32_t
+Platform::MakeDirectory (const FileSpec &spec,
+ mode_t mode)
+{
+ std::string path(spec.GetPath());
+ return this->MakeDirectory(path,mode);
+}
+
+Error
+Platform::PutFile (const FileSpec& source,
+ const FileSpec& destination,
+ uint32_t uid,
+ uint32_t gid)
+{
+ Error error("unimplemented");
+ return error;
+}
+
+Error
+Platform::GetFile (const FileSpec& source,
+ const FileSpec& destination)
+{
+ Error error("unimplemented");
+ return error;
+}
+
+bool
+Platform::GetFileExists (const lldb_private::FileSpec& file_spec)
+{
+ return false;
+}
+
+lldb_private::Error
+Platform::RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish
+{
+ if (IsHost())
+ return Host::RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ return Error("unimplemented");
+}
+
+
+bool
+Platform::CalculateMD5 (const FileSpec& file_spec,
+ uint64_t &low,
+ uint64_t &high)
+{
+ if (IsHost())
+ return Host::CalculateMD5(file_spec, low, high);
+ else
+ return false;
+}
+
+void
+Platform::SetLocalCacheDirectory (const char* local)
+{
+ m_local_cache_directory.assign(local);
+}
+
+const char*
+Platform::GetLocalCacheDirectory ()
+{
+ return m_local_cache_directory.c_str();
+}
+
+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." },
+};
+
+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." },
+};
+
+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." },
+};
+
+OptionGroupPlatformRSync::OptionGroupPlatformRSync ()
+{
+}
+
+OptionGroupPlatformRSync::~OptionGroupPlatformRSync ()
+{
+}
+
+const lldb_private::OptionDefinition*
+OptionGroupPlatformRSync::GetDefinitions ()
+{
+ return g_rsync_option_table;
+}
+
+void
+OptionGroupPlatformRSync::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_rsync = false;
+ m_rsync_opts.clear();
+ m_rsync_prefix.clear();
+ m_ignores_remote_hostname = false;
+}
+
+lldb_private::Error
+OptionGroupPlatformRSync::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error;
+ char short_option = (char) GetDefinitions()[option_idx].short_option;
+ switch (short_option)
+ {
+ case 'r':
+ m_rsync = true;
+ break;
+
+ case 'R':
+ m_rsync_opts.assign(option_arg);
+ break;
+
+ case 'P':
+ m_rsync_prefix.assign(option_arg);
+ break;
+
+ case 'i':
+ m_ignores_remote_hostname = true;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+ return error;
}
+uint32_t
+OptionGroupPlatformRSync::GetNumDefinitions ()
+{
+ return llvm::array_lengthof(g_rsync_option_table);
+}
lldb::BreakpointSP
Platform::SetThreadCreationBreakpoint (lldb_private::Target &target)
@@ -770,10 +939,108 @@ Platform::SetThreadCreationBreakpoint (lldb_private::Target &target)
return lldb::BreakpointSP();
}
+OptionGroupPlatformSSH::OptionGroupPlatformSSH ()
+{
+}
+
+OptionGroupPlatformSSH::~OptionGroupPlatformSSH ()
+{
+}
+
+const lldb_private::OptionDefinition*
+OptionGroupPlatformSSH::GetDefinitions ()
+{
+ return g_ssh_option_table;
+}
+
+void
+OptionGroupPlatformSSH::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_ssh = false;
+ m_ssh_opts.clear();
+}
+
+lldb_private::Error
+OptionGroupPlatformSSH::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error;
+ char short_option = (char) GetDefinitions()[option_idx].short_option;
+ switch (short_option)
+ {
+ case 's':
+ m_ssh = true;
+ break;
+
+ case 'S':
+ m_ssh_opts.assign(option_arg);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+}
+
+uint32_t
+OptionGroupPlatformSSH::GetNumDefinitions ()
+{
+ return llvm::array_lengthof(g_ssh_option_table);
+}
+
+OptionGroupPlatformCaching::OptionGroupPlatformCaching ()
+{
+}
+
+OptionGroupPlatformCaching::~OptionGroupPlatformCaching ()
+{
+}
+
+const lldb_private::OptionDefinition*
+OptionGroupPlatformCaching::GetDefinitions ()
+{
+ return g_caching_option_table;
+}
+
+void
+OptionGroupPlatformCaching::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_cache_dir.clear();
+}
+
+lldb_private::Error
+OptionGroupPlatformCaching::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error;
+ char short_option = (char) GetDefinitions()[option_idx].short_option;
+ switch (short_option)
+ {
+ case 'c':
+ m_cache_dir.assign(option_arg);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+}
+
+uint32_t
+OptionGroupPlatformCaching::GetNumDefinitions ()
+{
+ return llvm::array_lengthof(g_caching_option_table);
+}
+
size_t
Platform::GetEnvironment (StringList &environment)
{
environment.Clear();
return false;
}
-
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index 6edb9390d990..700afdb7981a 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -35,12 +35,17 @@
#include "lldb/Target/Platform.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanBase.h"
+#ifndef LLDB_DISABLE_POSIX
+#include <spawn.h>
+#endif
+
using namespace lldb;
using namespace lldb_private;
@@ -485,7 +490,8 @@ bool
ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error,
bool localhost,
bool will_debug,
- bool first_arg_is_full_shell_command)
+ bool first_arg_is_full_shell_command,
+ int32_t num_resumes)
{
error.Clear();
@@ -567,14 +573,14 @@ ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error,
// 1 - stop in shell
// 2 - stop in /usr/bin/arch
// 3 - then we will stop in our program
- SetResumeCount(2);
+ SetResumeCount(num_resumes + 1);
}
else
{
// Set the resume count to 1:
// 1 - stop in shell
// 2 - then we will stop in our program
- SetResumeCount(1);
+ SetResumeCount(num_resumes);
}
}
@@ -663,8 +669,9 @@ ProcessLaunchInfo::FileAction::Duplicate (int fd, int dup_fd)
+#ifndef LLDB_DISABLE_POSIX
bool
-ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (posix_spawn_file_actions_t *file_actions,
+ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (void *_file_actions,
const FileAction *info,
Log *log,
Error& error)
@@ -672,6 +679,8 @@ ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (posix_spawn_file_actions
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:
@@ -733,6 +742,7 @@ ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (posix_spawn_file_actions
}
return error.Success();
}
+#endif
Error
ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
@@ -808,7 +818,7 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op
if (option_arg && option_arg[0])
launch_info.SetShell (option_arg);
else
- launch_info.SetShell ("/bin/bash");
+ launch_info.SetShell (LLDB_DEFAULT_SHELL);
break;
case 'v':
@@ -826,21 +836,21 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op
OptionDefinition
ProcessLaunchCommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
-{ LLDB_OPT_SET_ALL, false, "disable-aslr", 'A', no_argument, NULL, 0, eArgTypeNone, "Disable address space layout randomization when launching a process."},
-{ LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
-{ LLDB_OPT_SET_ALL, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."},
-{ LLDB_OPT_SET_ALL, false, "arch", 'a', required_argument, NULL, 0, eArgTypeArchitecture, "Set the architecture for the process to launch when ambiguous."},
-{ LLDB_OPT_SET_ALL, false, "environment", 'v', required_argument, NULL, 0, eArgTypeNone, "Specify an environment variable name/value stirng (--environement NAME=VALUE). Can be specified multiple times for subsequent environment entries."},
-{ LLDB_OPT_SET_ALL, false, "shell", 'c', optional_argument, 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, 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_1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypeFilename, "Redirect stdin for the process to <filename>."},
-{ LLDB_OPT_SET_1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypeFilename, "Redirect stdout for the process to <filename>."},
-{ LLDB_OPT_SET_1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypeFilename, "Redirect stderr for the process to <filename>."},
+{ 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_2 , false, "tty", 't', no_argument, NULL, 0, eArgTypeNone, "Start the process in a terminal (not supported on all platforms)."},
+{ 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_3 , false, "no-stdio", 'n', no_argument, 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, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
{ 0 , false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
@@ -1134,6 +1144,7 @@ Process::Finalize()
m_dynamic_checkers_ap.reset();
m_abi_sp.reset();
m_os_ap.reset();
+ m_system_runtime_ap.reset();
m_dyld_ap.reset();
m_thread_list_real.Destroy();
m_thread_list.Destroy();
@@ -1221,7 +1232,7 @@ Process::GetNextEvent (EventSP &event_sp)
StateType
-Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr)
+Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr, bool wait_always)
{
// We can't just wait for a "stopped" event, because the stopped event may have restarted the target.
// We have to actually check each event, and in the case of a stopped event check the restarted flag
@@ -1234,6 +1245,19 @@ Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp
if (state == eStateDetached || state == eStateExited)
return state;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf ("Process::%s (timeout = %p)", __FUNCTION__, timeout);
+
+ if (!wait_always &&
+ StateIsStoppedState(state, true) &&
+ StateIsStoppedState(GetPrivateState(), true)) {
+ if (log)
+ log->Printf("Process::%s returning without waiting for events; process private and public states are already 'stopped'.",
+ __FUNCTION__);
+ return state;
+ }
+
while (state != eStateInvalid)
{
EventSP event_sp;
@@ -1792,35 +1816,36 @@ Process::LoadImage (const FileSpec &image_spec, Error &error)
{
ExecutionContext exe_ctx;
frame_sp->CalculateExecutionContext (exe_ctx);
- const bool unwind_on_error = true;
- const bool ignore_breakpoints = true;
+ EvaluateExpressionOptions expr_options;
+ expr_options.SetUnwindOnError(true);
+ expr_options.SetIgnoreBreakpoints(true);
+ expr_options.SetExecutionPolicy(eExecutionPolicyAlways);
StreamString expr;
expr.Printf("dlopen (\"%s\", 2)", path);
const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
lldb::ValueObjectSP result_valobj_sp;
+ Error expr_error;
ClangUserExpression::Evaluate (exe_ctx,
- eExecutionPolicyAlways,
- lldb::eLanguageTypeUnknown,
- ClangUserExpression::eResultTypeAny,
- unwind_on_error,
- ignore_breakpoints,
+ expr_options,
expr.GetData(),
prefix,
result_valobj_sp,
- true,
- ClangUserExpression::kDefaultTimeout);
- error = result_valobj_sp->GetError();
- if (error.Success())
+ expr_error);
+ if (expr_error.Success())
{
- Scalar scalar;
- if (result_valobj_sp->ResolveValue (scalar))
+ error = result_valobj_sp->GetError();
+ if (error.Success())
{
- addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
- if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS)
+ Scalar scalar;
+ if (result_valobj_sp->ResolveValue (scalar))
{
- uint32_t image_token = m_image_tokens.size();
- m_image_tokens.push_back (image_ptr);
- return image_token;
+ addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
+ if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS)
+ {
+ uint32_t image_token = m_image_tokens.size();
+ m_image_tokens.push_back (image_ptr);
+ return image_token;
+ }
}
}
}
@@ -1869,23 +1894,21 @@ Process::UnloadImage (uint32_t image_token)
{
ExecutionContext exe_ctx;
frame_sp->CalculateExecutionContext (exe_ctx);
- const bool unwind_on_error = true;
- const bool ignore_breakpoints = true;
+ EvaluateExpressionOptions expr_options;
+ expr_options.SetUnwindOnError(true);
+ expr_options.SetIgnoreBreakpoints(true);
+ expr_options.SetExecutionPolicy(eExecutionPolicyAlways);
StreamString expr;
expr.Printf("dlclose ((void *)0x%" PRIx64 ")", image_addr);
const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
lldb::ValueObjectSP result_valobj_sp;
+ Error expr_error;
ClangUserExpression::Evaluate (exe_ctx,
- eExecutionPolicyAlways,
- lldb::eLanguageTypeUnknown,
- ClangUserExpression::eResultTypeAny,
- unwind_on_error,
- ignore_breakpoints,
+ expr_options,
expr.GetData(),
prefix,
result_valobj_sp,
- true,
- ClangUserExpression::kDefaultTimeout);
+ expr_error);
if (result_valobj_sp->GetError().Success())
{
Scalar scalar;
@@ -2072,11 +2095,21 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw
bp_site_sp.reset (new BreakpointSite (&m_breakpoint_site_list, owner, load_addr, use_hardware));
if (bp_site_sp)
{
- if (EnableBreakpointSite (bp_site_sp.get()).Success())
+ Error error = EnableBreakpointSite (bp_site_sp.get());
+ if (error.Success())
{
owner->SetBreakpointSite (bp_site_sp);
return m_breakpoint_site_list.Add (bp_site_sp);
}
+ else
+ {
+ // Report error for setting breakpoint...
+ m_target.GetDebugger().GetErrorFile().Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
+ load_addr,
+ owner->GetBreakpoint().GetID(),
+ owner->GetID(),
+ error.AsCString() ? error.AsCString() : "unkown error");
+ }
}
}
}
@@ -2722,8 +2755,8 @@ Process::AllocateMemory(size_t size, uint32_t permissions, Error &error)
addr_t allocated_addr = DoAllocateMemory (size, permissions, error);
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
- log->Printf("Process::AllocateMemory(size=%4zu, permissions=%s) => 0x%16.16" PRIx64 " (m_stop_id = %u m_memory_id = %u)",
- size,
+ log->Printf("Process::AllocateMemory(size=%" PRIu64 ", permissions=%s) => 0x%16.16" PRIx64 " (m_stop_id = %u m_memory_id = %u)",
+ (uint64_t)size,
GetPermissionsAsCString (permissions),
(uint64_t)allocated_addr,
m_mod_id.GetStopID(),
@@ -2845,6 +2878,7 @@ Process::Launch (const ProcessLaunchInfo &launch_info)
Error error;
m_abi_sp.reset();
m_dyld_ap.reset();
+ m_system_runtime_ap.reset();
m_os_ap.reset();
m_process_input_reader.reset();
@@ -2913,6 +2947,10 @@ Process::Launch (const ProcessLaunchInfo &launch_info)
if (dyld)
dyld->DidLaunch();
+ SystemRuntime *system_runtime = GetSystemRuntime ();
+ if (system_runtime)
+ system_runtime->DidLaunch();
+
m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
// This delays passing the stopped event to listeners till DidLaunch gets
// a chance to complete...
@@ -2956,6 +2994,10 @@ Process::LoadCore ()
if (dyld)
dyld->DidAttach();
+ SystemRuntime *system_runtime = GetSystemRuntime ();
+ if (system_runtime)
+ system_runtime->DidAttach();
+
m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
// We successfully loaded a core file, now pretend we stopped so we can
// show all of the threads in the core file and explore the crashed
@@ -2974,6 +3016,14 @@ Process::GetDynamicLoader ()
return m_dyld_ap.get();
}
+SystemRuntime *
+Process::GetSystemRuntime ()
+{
+ if (m_system_runtime_ap.get() == NULL)
+ m_system_runtime_ap.reset (SystemRuntime::FindPlugin(this));
+ return m_system_runtime_ap.get();
+}
+
Process::NextEventAction::EventActionResult
Process::AttachCompletionHandler::PerformAction (lldb::EventSP &event_sp)
@@ -3036,6 +3086,7 @@ Process::Attach (ProcessAttachInfo &attach_info)
m_abi_sp.reset();
m_process_input_reader.reset();
m_dyld_ap.reset();
+ m_system_runtime_ap.reset();
m_os_ap.reset();
lldb::pid_t attach_pid = attach_info.GetProcessID();
@@ -3208,6 +3259,10 @@ Process::CompleteAttach ()
if (dyld)
dyld->DidAttach();
+ SystemRuntime *system_runtime = GetSystemRuntime ();
+ if (system_runtime)
+ system_runtime->DidAttach();
+
m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
// Figure out which one is the executable, and set that in our target:
const ModuleList &target_modules = m_target.GetImages();
@@ -3968,15 +4023,15 @@ Process::HandlePrivateEvent (EventSP &event_sp)
m_currently_handling_event.SetValue(false, eBroadcastAlways);
}
-void *
+thread_result_t
Process::PrivateStateThread (void *arg)
{
Process *proc = static_cast<Process*> (arg);
- void *result = proc->RunPrivateStateThread ();
+ thread_result_t result = proc->RunPrivateStateThread();
return result;
}
-void *
+thread_result_t
Process::RunPrivateStateThread ()
{
bool control_only = true;
@@ -5095,15 +5150,15 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
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 %" PRId64 " usec with all threads enabled.",
+ "running till for %" PRIu64 " usec with all threads enabled.",
remaining_time);
else
log->Printf ("Process::RunThreadPlan(): Restarting function with all threads enabled "
- "and timeout: %d timed out, abandoning execution.",
+ "and timeout: %u timed out, abandoning execution.",
timeout_usec);
}
else
- log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
+ log->Printf ("Process::RunThreadPlan(): Running function with timeout: %u timed out, "
"abandoning execution.",
timeout_usec);
}
@@ -5349,7 +5404,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
log->Printf("Process::RunThreadPlan(): execution interrupted: %s", s.GetData());
}
- if (should_unwind && thread_plan_sp)
+ if (should_unwind)
{
if (log)
log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.", thread_plan_sp.get());
@@ -5367,7 +5422,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (log)
log->PutCString("Process::RunThreadPlan(): execution set up error.");
- if (unwind_on_error && thread_plan_sp)
+ if (unwind_on_error)
{
thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
thread_plan_sp->SetPrivate (orig_plan_private);
@@ -5578,11 +5633,10 @@ Process::DidExec ()
{
Target &target = GetTarget();
target.CleanupProcess ();
- ModuleList unloaded_modules (target.GetImages());
- target.ModulesDidUnload (unloaded_modules);
- target.GetSectionLoadList().Clear();
+ target.ClearModules();
m_dynamic_checkers_ap.reset();
m_abi_sp.reset();
+ m_system_runtime_ap.reset();
m_os_ap.reset();
m_dyld_ap.reset();
m_image_tokens.clear();
@@ -5592,4 +5646,8 @@ Process::DidExec ()
m_memory_cache.Clear(true);
DoDidExec();
CompleteAttach ();
+ // Flush the process (threads and all stack frames) after running CompleteAttach()
+ // in case the dynamic loader loaded things in new locations.
+ Flush();
}
+
diff --git a/source/Target/RegisterContext.cpp b/source/Target/RegisterContext.cpp
index 0d89db724ab4..3d68ba8706c9 100644
--- a/source/Target/RegisterContext.cpp
+++ b/source/Target/RegisterContext.cpp
@@ -81,6 +81,15 @@ RegisterContext::GetRegisterInfoByName (const char *reg_name, uint32_t start_idx
return NULL;
}
+const RegisterInfo *
+RegisterContext::GetRegisterInfo (uint32_t kind, uint32_t num)
+{
+ const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ return NULL;
+ return GetRegisterInfoAtIndex (reg_num);
+}
+
const char *
RegisterContext::GetRegisterName (uint32_t reg)
{
@@ -113,6 +122,19 @@ RegisterContext::SetPC(uint64_t pc)
return success;
}
+bool
+RegisterContext::SetPC(Address addr)
+{
+ TargetSP target_sp = m_thread.CalculateTarget();
+ Target *target = target_sp.get();
+
+ lldb::addr_t callAddr = addr.GetCallableLoadAddress (target);
+ if (callAddr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ return SetPC (callAddr);
+}
+
uint64_t
RegisterContext::GetSP(uint64_t fail_value)
{
diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp
index 3c4c43d9f44c..a936a57d048d 100644
--- a/source/Target/StackFrame.cpp
+++ b/source/Target/StackFrame.cpp
@@ -48,7 +48,11 @@ StackFrame::StackFrame (const ThreadSP &thread_sp,
user_id_t frame_idx,
user_id_t unwind_frame_index,
addr_t cfa,
+ bool cfa_is_valid,
addr_t pc,
+ uint32_t stop_id,
+ bool stop_id_is_valid,
+ bool is_history_frame,
const SymbolContext *sc_ptr) :
m_thread_wp (thread_sp),
m_frame_index (frame_idx),
@@ -60,10 +64,21 @@ StackFrame::StackFrame (const ThreadSP &thread_sp,
m_flags (),
m_frame_base (),
m_frame_base_error (),
+ m_cfa_is_valid (cfa_is_valid),
+ m_stop_id (stop_id),
+ m_stop_id_is_valid (stop_id_is_valid),
+ m_is_history_frame (is_history_frame),
m_variable_list_sp (),
m_variable_list_value_objects (),
m_disassembly ()
{
+ // If we don't have a CFA value, use the frame index for our StackID so that recursive
+ // functions properly aren't confused with one another on a history stack.
+ if (m_is_history_frame && m_cfa_is_valid == false)
+ {
+ m_id.SetCFA (m_frame_index);
+ }
+
if (sc_ptr != NULL)
{
m_sc = *sc_ptr;
@@ -88,6 +103,10 @@ StackFrame::StackFrame (const ThreadSP &thread_sp,
m_flags (),
m_frame_base (),
m_frame_base_error (),
+ m_cfa_is_valid (true),
+ m_stop_id (0),
+ m_stop_id_is_valid (false),
+ m_is_history_frame (false),
m_variable_list_sp (),
m_variable_list_value_objects (),
m_disassembly ()
@@ -123,6 +142,10 @@ StackFrame::StackFrame (const ThreadSP &thread_sp,
m_flags (),
m_frame_base (),
m_frame_base_error (),
+ m_cfa_is_valid (true),
+ m_stop_id (0),
+ m_stop_id_is_valid (false),
+ m_is_history_frame (false),
m_variable_list_sp (),
m_variable_list_value_objects (),
m_disassembly ()
@@ -246,15 +269,19 @@ StackFrame::GetFrameCodeAddress()
return m_frame_code_addr;
}
-void
+bool
StackFrame::ChangePC (addr_t pc)
{
+ // We can't change the pc value of a history stack frame - it is immutable.
+ if (m_is_history_frame)
+ return false;
m_frame_code_addr.SetRawAddress(pc);
m_sc.Clear(false);
m_flags.Reset(0);
ThreadSP thread_sp (GetThread());
if (thread_sp)
thread_sp->ClearStackFrames ();
+ return true;
}
const char *
@@ -517,6 +544,10 @@ StackFrame::GetVariableList (bool get_file_globals)
VariableListSP
StackFrame::GetInScopeVariableList (bool get_file_globals)
{
+ // We can't fetch variable information for a history stack frame.
+ if (m_is_history_frame)
+ return VariableListSP();
+
VariableListSP var_list_sp(new VariableList);
GetSymbolContext (eSymbolContextCompUnit | eSymbolContextBlock);
@@ -549,6 +580,9 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
VariableSP &var_sp,
Error &error)
{
+ // We can't fetch variable information for a history stack frame.
+ if (m_is_history_frame)
+ return ValueObjectSP();
if (var_expr_cstr && var_expr_cstr[0])
{
@@ -1108,6 +1142,12 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
bool
StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
{
+ if (m_cfa_is_valid == false)
+ {
+ m_frame_base_error.SetErrorString("No frame base available for this historical stack frame.");
+ return false;
+ }
+
if (m_flags.IsClear(GOT_FRAME_BASE))
{
if (m_sc.function)
@@ -1172,6 +1212,10 @@ ValueObjectSP
StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic)
{
ValueObjectSP valobj_sp;
+ if (m_is_history_frame)
+ {
+ return valobj_sp;
+ }
VariableList *var_list = GetVariableList (true);
if (var_list)
{
@@ -1202,6 +1246,9 @@ StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, Dynam
ValueObjectSP
StackFrame::TrackGlobalVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic)
{
+ if (m_is_history_frame)
+ return ValueObjectSP();
+
// Check to make sure we aren't already tracking this variable?
ValueObjectSP valobj_sp (GetValueObjectForFrameVariable (variable_sp, use_dynamic));
if (!valobj_sp)
@@ -1275,7 +1322,7 @@ StackFrame::CalculateExecutionContext (ExecutionContext &exe_ctx)
}
void
-StackFrame::DumpUsingSettingsFormat (Stream *strm)
+StackFrame::DumpUsingSettingsFormat (Stream *strm, const char *frame_marker)
{
if (strm == NULL)
return;
@@ -1283,6 +1330,10 @@ StackFrame::DumpUsingSettingsFormat (Stream *strm)
GetSymbolContext(eSymbolContextEverything);
ExecutionContext exe_ctx (shared_from_this());
StreamString s;
+
+ if (frame_marker)
+ s.PutCString(frame_marker);
+
const char *frame_format = NULL;
Target *target = exe_ctx.GetTargetPtr();
if (target)
@@ -1370,13 +1421,14 @@ StackFrame::HasCachedData () const
bool
StackFrame::GetStatus (Stream& strm,
bool show_frame_info,
- bool show_source)
+ bool show_source,
+ const char *frame_marker)
{
if (show_frame_info)
{
strm.Indent();
- DumpUsingSettingsFormat (&strm);
+ DumpUsingSettingsFormat (&strm, frame_marker);
}
if (show_source)
diff --git a/source/Target/StackFrameList.cpp b/source/Target/StackFrameList.cpp
index 69309dfae7b6..eaac3613c93d 100644
--- a/source/Target/StackFrameList.cpp
+++ b/source/Target/StackFrameList.cpp
@@ -336,7 +336,10 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx)
SetAllFramesFetched();
break;
}
- unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(), m_frames.size(), idx, cfa, pc, NULL));
+ const bool cfa_is_valid = true;
+ const bool stop_id_is_valid = false;
+ const bool is_history_frame = false;
+ unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(), m_frames.size(), idx, cfa, cfa_is_valid, pc, 0, stop_id_is_valid, is_history_frame, NULL));
m_frames.push_back (unwind_frame_sp);
}
@@ -534,7 +537,10 @@ StackFrameList::GetFrameAtIndex (uint32_t idx)
addr_t pc, cfa;
if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
{
- frame_sp.reset (new StackFrame (m_thread.shared_from_this(), idx, idx, cfa, pc, NULL));
+ const bool cfa_is_valid = true;
+ const bool stop_id_is_valid = false;
+ const bool is_history_frame = false;
+ frame_sp.reset (new StackFrame (m_thread.shared_from_this(), idx, idx, cfa, cfa_is_valid, pc, 0, stop_id_is_valid, is_history_frame, NULL));
Function *function = frame_sp->GetSymbolContext (eSymbolContextFunction).function;
if (function)
@@ -863,7 +869,8 @@ StackFrameList::GetStatus (Stream& strm,
uint32_t first_frame,
uint32_t num_frames,
bool show_frame_info,
- uint32_t num_frames_with_source)
+ uint32_t num_frames_with_source,
+ const char *selected_frame_marker)
{
size_t num_frames_displayed = 0;
@@ -880,15 +887,34 @@ StackFrameList::GetStatus (Stream& strm,
else
last_frame = first_frame + num_frames;
+ StackFrameSP selected_frame_sp = m_thread.GetSelectedFrame();
+ const char *unselected_marker = NULL;
+ std::string buffer;
+ if (selected_frame_marker)
+ {
+ size_t len = strlen(selected_frame_marker);
+ buffer.insert(buffer.begin(), len, ' ');
+ unselected_marker = buffer.c_str();
+ }
+ const char *marker = NULL;
+
for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx)
{
frame_sp = GetFrameAtIndex(frame_idx);
if (frame_sp.get() == NULL)
break;
+ if (selected_frame_marker != NULL)
+ {
+ if (frame_sp == selected_frame_sp)
+ marker = selected_frame_marker;
+ else
+ marker = unselected_marker;
+ }
+
if (!frame_sp->GetStatus (strm,
show_frame_info,
- num_frames_with_source > (first_frame - frame_idx)))
+ num_frames_with_source > (first_frame - frame_idx), marker))
break;
++num_frames_displayed;
}
diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp
index 81b9d866f711..914969a633e6 100644
--- a/source/Target/StopInfo.cpp
+++ b/source/Target/StopInfo.cpp
@@ -694,22 +694,17 @@ 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;
+ EvaluateExpressionOptions expr_options;
+ expr_options.SetUnwindOnError(true);
+ expr_options.SetIgnoreBreakpoints(true);
ValueObjectSP result_value_sp;
- const bool unwind_on_error = true;
- const bool ignore_breakpoints = true;
Error error;
- result_code = ClangUserExpression::EvaluateWithError (exe_ctx,
- eExecutionPolicyOnlyWhenNeeded,
- lldb::eLanguageTypeUnknown,
- ClangUserExpression::eResultTypeAny,
- unwind_on_error,
- ignore_breakpoints,
- wp_sp->GetConditionText(),
- NULL,
- result_value_sp,
- error,
- true,
- ClangUserExpression::kDefaultTimeout);
+ result_code = ClangUserExpression::Evaluate (exe_ctx,
+ expr_options,
+ wp_sp->GetConditionText(),
+ NULL,
+ result_value_sp,
+ error);
if (result_code == eExecutionCompleted)
{
if (result_value_sp)
diff --git a/source/Target/SystemRuntime.cpp b/source/Target/SystemRuntime.cpp
new file mode 100644
index 000000000000..7ce150f41273
--- /dev/null
+++ b/source/Target/SystemRuntime.cpp
@@ -0,0 +1,73 @@
+//===-- SystemRuntime.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/SystemRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SystemRuntime*
+SystemRuntime::FindPlugin (Process *process)
+{
+ SystemRuntimeCreateInstance create_callback = NULL;
+ for (uint32_t idx = 0; (create_callback = PluginManager::GetSystemRuntimeCreateCallbackAtIndex(idx)) != NULL; ++idx)
+ {
+ std::unique_ptr<SystemRuntime> instance_ap(create_callback(process));
+ if (instance_ap.get())
+ return instance_ap.release();
+ }
+ return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// SystemRuntime constructor
+//----------------------------------------------------------------------
+SystemRuntime::SystemRuntime(Process *process) :
+ m_process (process)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SystemRuntime::~SystemRuntime()
+{
+}
+
+void
+SystemRuntime::DidAttach ()
+{
+}
+
+void
+SystemRuntime::DidLaunch()
+{
+}
+
+void
+SystemRuntime::ModulesDidLoad (ModuleList &module_list)
+{
+}
+
+std::vector<ConstString>
+SystemRuntime::GetExtendedBacktraceTypes ()
+{
+ std::vector<ConstString> types;
+ return types;
+}
+
+ThreadSP
+SystemRuntime::GetExtendedBacktrace (ThreadSP thread, ConstString type)
+{
+ return ThreadSP();
+}
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 5766b737c7d8..18efd8cb7247 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -43,6 +43,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
@@ -83,8 +84,7 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
m_source_manager_ap(),
m_stop_hooks (),
m_stop_hook_next_id (0),
- m_suppress_stop_hooks (false),
- m_suppress_synthetic_value(false)
+ m_suppress_stop_hooks (false)
{
SetEventName (eBroadcastBitBreakpointChanged, "breakpoint-changed");
SetEventName (eBroadcastBitModulesLoaded, "modules-loaded");
@@ -192,7 +192,7 @@ Target::Destroy()
DeleteCurrentProcess ();
m_platform_sp.reset();
m_arch.Clear();
- m_images.Clear();
+ ClearModules();
m_section_load_list.Clear();
const bool notify = false;
m_breakpoint_list.RemoveAll(notify);
@@ -201,14 +201,10 @@ Target::Destroy()
m_last_created_watchpoint.reset();
m_search_filter_sp.reset();
m_image_search_paths.Clear(notify);
- m_scratch_ast_context_ap.reset();
- m_scratch_ast_source_ap.reset();
- m_ast_importer_ap.reset();
m_persistent_variables.Clear();
m_stop_hooks.clear();
m_stop_hook_next_id = 0;
m_suppress_stop_hooks = false;
- m_suppress_synthetic_value = false;
}
@@ -247,11 +243,12 @@ BreakpointSP
Target::CreateSourceRegexBreakpoint (const FileSpecList *containingModules,
const FileSpecList *source_file_spec_list,
RegularExpression &source_regex,
- bool internal)
+ bool internal,
+ bool hardware)
{
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, source_file_spec_list));
BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex (NULL, source_regex));
- return CreateBreakpoint (filter_sp, resolver_sp, internal);
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
}
@@ -261,7 +258,8 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
uint32_t line_no,
LazyBool check_inlines,
LazyBool skip_prologue,
- bool internal)
+ bool internal,
+ bool hardware)
{
if (check_inlines == eLazyBoolCalculate)
{
@@ -304,12 +302,12 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
line_no,
check_inlines,
skip_prologue));
- return CreateBreakpoint (filter_sp, resolver_sp, internal);
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
}
BreakpointSP
-Target::CreateBreakpoint (lldb::addr_t addr, bool internal)
+Target::CreateBreakpoint (lldb::addr_t addr, bool internal, bool hardware)
{
Address so_addr;
// Attempt to resolve our load address if possible, though it is ok if
@@ -322,16 +320,16 @@ Target::CreateBreakpoint (lldb::addr_t addr, bool internal)
// The address didn't resolve, so just set this as an absolute address
so_addr.SetOffset (addr);
}
- BreakpointSP bp_sp (CreateBreakpoint(so_addr, internal));
+ BreakpointSP bp_sp (CreateBreakpoint(so_addr, internal, hardware));
return bp_sp;
}
BreakpointSP
-Target::CreateBreakpoint (Address &addr, bool internal)
+Target::CreateBreakpoint (Address &addr, bool internal, bool hardware)
{
SearchFilterSP filter_sp(new SearchFilterForNonModuleSpecificSearches (shared_from_this()));
BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, addr));
- return CreateBreakpoint (filter_sp, resolver_sp, internal);
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
}
BreakpointSP
@@ -340,7 +338,8 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
const char *func_name,
uint32_t func_name_type_mask,
LazyBool skip_prologue,
- bool internal)
+ bool internal,
+ bool hardware)
{
BreakpointSP bp_sp;
if (func_name)
@@ -355,7 +354,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
func_name_type_mask,
Breakpoint::Exact,
skip_prologue));
- bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal);
+ bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
}
return bp_sp;
}
@@ -366,7 +365,8 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
const std::vector<std::string> &func_names,
uint32_t func_name_type_mask,
LazyBool skip_prologue,
- bool internal)
+ bool internal,
+ bool hardware)
{
BreakpointSP bp_sp;
size_t num_names = func_names.size();
@@ -381,7 +381,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
func_names,
func_name_type_mask,
skip_prologue));
- bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal);
+ bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
}
return bp_sp;
}
@@ -393,7 +393,8 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
size_t num_names,
uint32_t func_name_type_mask,
LazyBool skip_prologue,
- bool internal)
+ bool internal,
+ bool hardware)
{
BreakpointSP bp_sp;
if (num_names > 0)
@@ -408,7 +409,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
num_names,
func_name_type_mask,
skip_prologue));
- bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal);
+ bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
}
return bp_sp;
}
@@ -478,14 +479,15 @@ Target::CreateFuncRegexBreakpoint (const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
RegularExpression &func_regex,
LazyBool skip_prologue,
- bool internal)
+ bool internal,
+ bool hardware)
{
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, containingSourceFiles));
BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL,
func_regex,
skip_prologue == eLazyBoolCalculate ? GetSkipPrologue() : skip_prologue));
- return CreateBreakpoint (filter_sp, resolver_sp, internal);
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
}
lldb::BreakpointSP
@@ -495,12 +497,12 @@ Target::CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_
}
BreakpointSP
-Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal)
+Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal, bool request_hardware)
{
BreakpointSP bp_sp;
if (filter_sp && resolver_sp)
{
- bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp));
+ bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp, request_hardware));
resolver_sp->SetBreakpoint (bp_sp.get());
if (internal)
@@ -630,7 +632,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 %lu is not supported", size);
+ error.SetErrorStringWithFormat("watch size of %zu is not supported", size);
}
wp_sp.reset();
}
@@ -1012,13 +1014,21 @@ LoadScriptingResourceForModule (const ModuleSP &module_sp, Target *target)
}
void
-Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
+Target::ClearModules()
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TARGET));
+ ModulesDidUnload (m_images, true);
+ GetSectionLoadList().Clear();
m_images.Clear();
m_scratch_ast_context_ap.reset();
m_scratch_ast_source_ap.reset();
m_ast_importer_ap.reset();
+}
+
+void
+Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TARGET));
+ ClearModules();
if (executable_sp.get())
{
@@ -1087,10 +1097,8 @@ Target::SetArchitecture (const ArchSpec &arch_spec)
log->Printf ("Target::SetArchitecture changing architecture to %s (%s)", arch_spec.GetArchitectureName(), arch_spec.GetTriple().getTriple().c_str());
m_arch = arch_spec;
ModuleSP executable_sp = GetExecutableModule ();
- m_images.Clear();
- m_scratch_ast_context_ap.reset();
- m_scratch_ast_source_ap.reset();
- m_ast_importer_ap.reset();
+
+ ClearModules();
// Need to do something about unsetting breakpoints.
if (executable_sp)
@@ -1135,7 +1143,7 @@ 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);
+ ModulesDidUnload (my_module_list, false);
}
void
@@ -1150,7 +1158,15 @@ Target::ModulesDidLoad (ModuleList &module_list)
{
if (module_list.GetSize())
{
- m_breakpoint_list.UpdateBreakpoints (module_list, true);
+ 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);
+ }
+ }
// TODO: make event data that packages up the module_list
BroadcastEvent (eBroadcastBitModulesLoaded, NULL);
}
@@ -1171,17 +1187,17 @@ Target::SymbolsDidLoad (ModuleList &module_list)
}
}
- m_breakpoint_list.UpdateBreakpoints (module_list, true);
+ m_breakpoint_list.UpdateBreakpoints (module_list, true, false);
BroadcastEvent(eBroadcastBitSymbolsLoaded, NULL);
}
}
void
-Target::ModulesDidUnload (ModuleList &module_list)
+Target::ModulesDidUnload (ModuleList &module_list, bool delete_locations)
{
if (module_list.GetSize())
{
- m_breakpoint_list.UpdateBreakpoints (module_list, false);
+ m_breakpoint_list.UpdateBreakpoints (module_list, false, delete_locations);
// TODO: make event data that packages up the module_list
BroadcastEvent (eBroadcastBitModulesUnloaded, NULL);
}
@@ -1724,10 +1740,7 @@ Target::ImageSearchPathsChanged
Target *target = (Target *)baton;
ModuleSP exe_module_sp (target->GetExecutableModule());
if (exe_module_sp)
- {
- target->m_images.Clear();
target->SetExecutableModule (exe_module_sp, true);
- }
}
ClangASTContext *
@@ -1875,18 +1888,13 @@ Target::EvaluateExpression
else
{
const char *prefix = GetExpressionPrefixContentsAsCString();
-
+ Error error;
execution_results = ClangUserExpression::Evaluate (exe_ctx,
- options.GetExecutionPolicy(),
- lldb::eLanguageTypeUnknown,
- options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny,
- options.DoesUnwindOnError(),
- options.DoesIgnoreBreakpoints(),
- expr_cstr,
+ options,
+ expr_cstr,
prefix,
result_valobj_sp,
- options.GetRunOthers(),
- options.GetTimeoutUsec());
+ error);
}
m_suppress_stop_hooks = old_suppress_value;
diff --git a/source/Target/TargetList.cpp b/source/Target/TargetList.cpp
index 8d907f432697..c4da84fbf8be 100644
--- a/source/Target/TargetList.cpp
+++ b/source/Target/TargetList.cpp
@@ -363,7 +363,7 @@ TargetList::FindTargetWithExecutableAndArchitecture
{
Mutex::Locker locker (m_target_list_mutex);
TargetSP target_sp;
- bool full_match = exe_file_spec.GetDirectory();
+ bool full_match = (bool)exe_file_spec.GetDirectory();
collection::const_iterator pos, end = m_target_list.end();
for (pos = m_target_list.begin(); pos != end; ++pos)
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index b65434bf9482..98c26019b4a1 100644
--- a/source/Target/Thread.cpp
+++ b/source/Target/Thread.cpp
@@ -282,12 +282,18 @@ Thread::~Thread()
void
Thread::DestroyThread ()
{
- // Tell any plans on the plan stack that the thread is being destroyed since
- // any active plans that have a thread go away in the middle of might need
- // to do cleanup.
+ // Tell any plans on the plan stacks that the thread is being destroyed since
+ // any plans that have a thread go away in the middle of might need
+ // to do cleanup, or in some cases NOT do cleanup...
for (auto plan : m_plan_stack)
plan->ThreadDestroyed();
+ for (auto plan : m_discarded_plan_stack)
+ plan->ThreadDestroyed();
+
+ for (auto plan : m_completed_plan_stack)
+ plan->ThreadDestroyed();
+
m_destroy_called = true;
m_plan_stack.clear();
m_discarded_plan_stack.clear();
@@ -1745,6 +1751,79 @@ Thread::ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return
return return_error;
}
+static void DumpAddressList (Stream &s, const std::vector<Address> &list, ExecutionContextScope *exe_scope)
+{
+ for (size_t n=0;n<list.size();n++)
+ {
+ s << "\t";
+ list[n].Dump (&s, exe_scope, Address::DumpStyleResolvedDescription, Address::DumpStyleSectionNameOffset);
+ s << "\n";
+ }
+}
+
+Error
+Thread::JumpToLine (const FileSpec &file, uint32_t line, bool can_leave_function, std::string *warnings)
+{
+ ExecutionContext exe_ctx (GetStackFrameAtIndex(0));
+ Target *target = exe_ctx.GetTargetPtr();
+ TargetSP target_sp = exe_ctx.GetTargetSP();
+ RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
+ StackFrame *frame = exe_ctx.GetFramePtr();
+ const SymbolContext &sc = frame->GetSymbolContext(eSymbolContextFunction);
+
+ // Find candidate locations.
+ std::vector<Address> candidates, within_function, outside_function;
+ target->GetImages().FindAddressesForLine (target_sp, file, line, sc.function, within_function, outside_function);
+
+ // If possible, we try and stay within the current function.
+ // Within a function, we accept multiple locations (optimized code may do this,
+ // there's no solution here so we do the best we can).
+ // However if we're trying to leave the function, we don't know how to pick the
+ // right location, so if there's more than one then we bail.
+ if (!within_function.empty())
+ candidates = within_function;
+ else if (outside_function.size() == 1 && can_leave_function)
+ candidates = outside_function;
+
+ // Check if we got anything.
+ if (candidates.empty())
+ {
+ if (outside_function.empty())
+ {
+ return Error("Cannot locate an address for %s:%i.",
+ file.GetFilename().AsCString(), line);
+ }
+ else if (outside_function.size() == 1)
+ {
+ return Error("%s:%i is outside the current function.",
+ file.GetFilename().AsCString(), line);
+ }
+ else
+ {
+ StreamString sstr;
+ DumpAddressList(sstr, outside_function, target);
+ return Error("%s:%i has multiple candidate locations:\n%s",
+ file.GetFilename().AsCString(), line, sstr.GetString().c_str());
+ }
+ }
+
+ // Accept the first location, warn about any others.
+ Address dest = candidates[0];
+ if (warnings && candidates.size() > 1)
+ {
+ StreamString sstr;
+ sstr.Printf("%s:%i appears multiple times in this function, selecting the first location:\n",
+ file.GetFilename().AsCString(), line);
+ DumpAddressList(sstr, candidates, target);
+ *warnings = sstr.GetString();
+ }
+
+ if (!reg_ctx->SetPC (dest))
+ return Error("Cannot change PC to target address.");
+
+ return Error();
+}
+
void
Thread::DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx)
{
@@ -1784,6 +1863,24 @@ Thread::SettingsTerminate ()
{
}
+lldb::addr_t
+Thread::GetThreadPointer ()
+{
+ return LLDB_INVALID_ADDRESS;
+}
+
+addr_t
+Thread::GetThreadLocalData (const ModuleSP module)
+{
+ // The default implementation is to ask the dynamic loader for it.
+ // This can be overridden for specific platforms.
+ DynamicLoader *loader = GetProcess()->GetDynamicLoader();
+ if (loader)
+ return loader->GetThreadLocalData (module, shared_from_this());
+ else
+ return LLDB_INVALID_ADDRESS;
+}
+
lldb::StackFrameSP
Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
{
@@ -1863,13 +1960,21 @@ Thread::GetStatus (Stream &strm, uint32_t start_frame, uint32_t num_frames, uint
strm.IndentMore();
const bool show_frame_info = true;
- strm.IndentMore ();
+
+ const char *selected_frame_marker = NULL;
+ if (num_frames == 1 || (GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID()))
+ strm.IndentMore ();
+ else
+ selected_frame_marker = "* ";
+
num_frames_shown = GetStackFrameList ()->GetStatus (strm,
start_frame,
num_frames,
show_frame_info,
- num_frames_with_source);
- strm.IndentLess();
+ num_frames_with_source,
+ selected_frame_marker);
+ if (num_frames == 1)
+ strm.IndentLess();
strm.IndentLess();
}
return num_frames_shown;
@@ -1944,6 +2049,7 @@ Thread::GetUnwinder ()
case llvm::Triple::x86:
case llvm::Triple::arm:
case llvm::Triple::thumb:
+ case llvm::Triple::mips64:
m_unwinder_ap.reset (new UnwindLLDB (*this));
break;
diff --git a/source/Target/ThreadPlanRunToAddress.cpp b/source/Target/ThreadPlanRunToAddress.cpp
index 86825d2eb26b..9e7713973054 100644
--- a/source/Target/ThreadPlanRunToAddress.cpp
+++ b/source/Target/ThreadPlanRunToAddress.cpp
@@ -88,7 +88,7 @@ ThreadPlanRunToAddress::SetInitialBreakpoints ()
for (size_t i = 0; i < num_addresses; i++)
{
Breakpoint *breakpoint;
- breakpoint = m_thread.CalculateTarget()->CreateBreakpoint (m_addresses[i], true).get();
+ breakpoint = m_thread.CalculateTarget()->CreateBreakpoint (m_addresses[i], true, false).get();
if (breakpoint != NULL)
{
m_break_ids[i] = breakpoint->GetID();
diff --git a/source/Target/ThreadPlanStepOut.cpp b/source/Target/ThreadPlanStepOut.cpp
index ba529587437d..c5efb5581527 100644
--- a/source/Target/ThreadPlanStepOut.cpp
+++ b/source/Target/ThreadPlanStepOut.cpp
@@ -102,7 +102,7 @@ ThreadPlanStepOut::ThreadPlanStepOut
if (m_return_addr == LLDB_INVALID_ADDRESS)
return;
- Breakpoint *return_bp = m_thread.CalculateTarget()->CreateBreakpoint (m_return_addr, true).get();
+ Breakpoint *return_bp = m_thread.CalculateTarget()->CreateBreakpoint (m_return_addr, true, false).get();
if (return_bp != NULL)
{
return_bp->SetThreadID(m_thread.GetID());
diff --git a/source/Target/ThreadPlanStepOverRange.cpp b/source/Target/ThreadPlanStepOverRange.cpp
index 7b8539ce422b..2d8108bf9b77 100644
--- a/source/Target/ThreadPlanStepOverRange.cpp
+++ b/source/Target/ThreadPlanStepOverRange.cpp
@@ -66,6 +66,32 @@ ThreadPlanStepOverRange::GetDescription (Stream *s, lldb::DescriptionLevel level
}
bool
+ThreadPlanStepOverRange::IsEquivalentContext(const SymbolContext &context)
+{
+
+ // Match as much as is specified in the m_addr_context:
+ // This is a fairly loose sanity check. Note, sometimes the target doesn't get filled
+ // in so I left out the target check. And sometimes the module comes in as the .o file from the
+ // inlined range, so I left that out too...
+ if (m_addr_context.comp_unit)
+ {
+ if (m_addr_context.comp_unit == context.comp_unit)
+ {
+ if (m_addr_context.function && m_addr_context.function == context.function)
+ {
+ if (m_addr_context.block && m_addr_context.block == context.block)
+ return true;
+ }
+ }
+ }
+ else if (m_addr_context.symbol && m_addr_context.symbol == context.symbol)
+ {
+ return true;
+ }
+ return false;
+}
+
+bool
ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
@@ -109,51 +135,29 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
{
// Make sure we really are in a new frame. Do that by unwinding and seeing if the
// start function really is our start function...
- StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(1);
-
- // But if we can't even unwind one frame we should just get out of here & stop...
- if (older_frame_sp)
+ for(uint32_t i = 1;; ++i)
{
- const SymbolContext &older_context = older_frame_sp->GetSymbolContext(eSymbolContextEverything);
-
- // Match as much as is specified in the m_addr_context:
- // This is a fairly loose sanity check. Note, sometimes the target doesn't get filled
- // in so I left out the target check. And sometimes the module comes in as the .o file from the
- // inlined range, so I left that out too...
-
- bool older_ctx_is_equivalent = true;
- if (m_addr_context.comp_unit)
- {
- if (m_addr_context.comp_unit == older_context.comp_unit)
- {
- if (m_addr_context.function && m_addr_context.function == older_context.function)
- {
- if (m_addr_context.block && m_addr_context.block == older_context.block)
- {
- older_ctx_is_equivalent = true;
- }
- }
- }
- }
- else if (m_addr_context.symbol && m_addr_context.symbol == older_context.symbol)
- {
- older_ctx_is_equivalent = true;
+ StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(i);
+ if (!older_frame_sp) {
+ // We can't unwind the next frame we should just get out of here & stop...
+ break;
}
-
- if (older_ctx_is_equivalent)
+
+ 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,
+ NULL,
+ true,
+ stop_others,
+ eVoteNo,
eVoteNoOpinion,
0);
+ break;
}
- else
+ else
{
new_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
-
}
}
}
diff --git a/source/Target/ThreadPlanStepRange.cpp b/source/Target/ThreadPlanStepRange.cpp
index 3940d542c10d..309f773c505b 100644
--- a/source/Target/ThreadPlanStepRange.cpp
+++ b/source/Target/ThreadPlanStepRange.cpp
@@ -173,6 +173,25 @@ ThreadPlanStepRange::InRange ()
log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData());
}
}
+ else if (new_context.line_entry.line == 0)
+ {
+ new_context.line_entry.line = m_addr_context.line_entry.line;
+ m_addr_context = new_context;
+ AddRange(m_addr_context.line_entry.range);
+ ret_value = true;
+ if (log)
+ {
+ StreamString s;
+ m_addr_context.line_entry.Dump (&s,
+ m_thread.CalculateTarget().get(),
+ true,
+ Address::DumpStyleLoadAddress,
+ Address::DumpStyleLoadAddress,
+ true);
+
+ log->Printf ("Step range plan stepped to a range at linenumber 0 stepping through that range: %s", s.GetData());
+ }
+ }
else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(m_thread.CalculateTarget().get())
!= pc_load_addr)
{
@@ -284,11 +303,13 @@ ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_
ExecutionContext exe_ctx (m_thread.GetProcess());
const char *plugin_name = NULL;
const char *flavor = NULL;
+ const bool prefer_file_cache = true;
m_instruction_ranges[i] = Disassembler::DisassembleRange(GetTarget().GetArchitecture(),
plugin_name,
flavor,
exe_ctx,
- m_address_ranges[i]);
+ m_address_ranges[i],
+ prefer_file_cache);
}
if (!m_instruction_ranges[i])
@@ -361,7 +382,7 @@ ThreadPlanStepRange::SetNextBranchBreakpoint ()
{
const bool is_internal = true;
run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress();
- m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal);
+ m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal, false);
if (m_next_branch_bp_sp)
{
if (log)
diff --git a/source/Target/ThreadPlanStepThrough.cpp b/source/Target/ThreadPlanStepThrough.cpp
index 92d1fcd850d8..37cd03c6986c 100644
--- a/source/Target/ThreadPlanStepThrough.cpp
+++ b/source/Target/ThreadPlanStepThrough.cpp
@@ -56,7 +56,7 @@ ThreadPlanStepThrough::ThreadPlanStepThrough (Thread &thread, StackID &m_stack_i
if (return_frame_sp)
{
m_backstop_addr = return_frame_sp->GetFrameCodeAddress().GetLoadAddress(m_thread.CalculateTarget().get());
- Breakpoint *return_bp = m_thread.GetProcess()->GetTarget().CreateBreakpoint (m_backstop_addr, true).get();
+ Breakpoint *return_bp = m_thread.GetProcess()->GetTarget().CreateBreakpoint (m_backstop_addr, true, false).get();
if (return_bp != NULL)
{
return_bp->SetThreadID(m_thread.GetID());
diff --git a/source/Target/ThreadPlanStepUntil.cpp b/source/Target/ThreadPlanStepUntil.cpp
index e1b5a0560c75..62e05c7fe342 100644
--- a/source/Target/ThreadPlanStepUntil.cpp
+++ b/source/Target/ThreadPlanStepUntil.cpp
@@ -68,7 +68,7 @@ ThreadPlanStepUntil::ThreadPlanStepUntil
{
// TODO: add inline functionality
m_return_addr = return_frame_sp->GetStackID().GetPC();
- Breakpoint *return_bp = target_sp->CreateBreakpoint (m_return_addr, true).get();
+ Breakpoint *return_bp = target_sp->CreateBreakpoint (m_return_addr, true, false).get();
if (return_bp != NULL)
{
return_bp->SetThreadID(thread_id);
@@ -82,7 +82,7 @@ ThreadPlanStepUntil::ThreadPlanStepUntil
// Now set breakpoints on all our return addresses:
for (size_t i = 0; i < num_addresses; i++)
{
- Breakpoint *until_bp = target_sp->CreateBreakpoint (address_list[i], true).get();
+ Breakpoint *until_bp = target_sp->CreateBreakpoint (address_list[i], true, false).get();
if (until_bp != NULL)
{
until_bp->SetThreadID(thread_id);
diff --git a/source/Target/UnixSignals.cpp b/source/Target/UnixSignals.cpp
index 7fe81f85e857..16a35b5f5a2f 100644
--- a/source/Target/UnixSignals.cpp
+++ b/source/Target/UnixSignals.cpp
@@ -74,13 +74,13 @@ UnixSignals::Reset ()
AddSignal (11, "SIGSEGV", "SEGV", false, true , true , "segmentation violation");
AddSignal (12, "SIGSYS", "SYS", false, true , true , "bad argument to system call");
AddSignal (13, "SIGPIPE", "PIPE", false, true , true , "write on a pipe with no one to read it");
- AddSignal (14, "SIGALRM", "ALRM", false, false, true , "alarm clock");
+ AddSignal (14, "SIGALRM", "ALRM", false, false, false, "alarm clock");
AddSignal (15, "SIGTERM", "TERM", false, true , true , "software termination signal from kill");
AddSignal (16, "SIGURG", "URG", false, false, false, "urgent condition on IO channel");
AddSignal (17, "SIGSTOP", "STOP", true , true , true , "sendable stop signal not from tty");
AddSignal (18, "SIGTSTP", "TSTP", false, true , true , "stop signal from tty");
AddSignal (19, "SIGCONT", "CONT", false, true , true , "continue a stopped process");
- AddSignal (20, "SIGCHLD", "CHLD", false, false, true , "to parent on child stop or exit");
+ AddSignal (20, "SIGCHLD", "CHLD", false, false, false, "to parent on child stop or exit");
AddSignal (21, "SIGTTIN", "TTIN", false, true , true , "to readers process group upon background tty read");
AddSignal (22, "SIGTTOU", "TTOU", false, true , true , "to readers process group upon background tty write");
AddSignal (23, "SIGIO", "IO", false, false, false, "input/output possible signal");
diff --git a/source/Utility/PseudoTerminal.cpp b/source/Utility/PseudoTerminal.cpp
index e4b444c36873..98d581def4c3 100644
--- a/source/Utility/PseudoTerminal.cpp
+++ b/source/Utility/PseudoTerminal.cpp
@@ -17,6 +17,21 @@
#include <sys/ioctl.h>
#endif
+#ifdef _WIN32
+#include "lldb/Host/windows/win32.h"
+// empty functions
+int posix_openpt(int flag) { return 0; }
+
+int strerror_r(int errnum, char *buf, size_t buflen) { return 0; }
+
+int unlockpt(int fd) { return 0; }
+int grantpt(int fd) { return 0; }
+char *ptsname(int fd) { return 0; }
+
+pid_t fork(void) { return 0; }
+pid_t setsid(void) { return 0; }
+#endif
+
using namespace lldb_utility;
//----------------------------------------------------------------------
diff --git a/source/Utility/RefCounter.cpp b/source/Utility/RefCounter.cpp
deleted file mode 100644
index c3acedd2f056..000000000000
--- a/source/Utility/RefCounter.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===---------------------RefCounter.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/RefCounter.h"
-
-namespace lldb_utility {
-
-RefCounter::RefCounter(RefCounter::value_type* ctr):
-m_counter(ctr)
-{
- increment(m_counter);
-}
-
-RefCounter::~RefCounter()
-{
- decrement(m_counter);
-}
-
-} // namespace lldb_utility
diff --git a/source/Utility/SharingPtr.cpp b/source/Utility/SharingPtr.cpp
index f64d7e3995b8..be237cec61c4 100644
--- a/source/Utility/SharingPtr.cpp
+++ b/source/Utility/SharingPtr.cpp
@@ -138,13 +138,21 @@ namespace imp
void
shared_count::add_shared()
{
- increment(shared_owners_);
+#ifdef _MSC_VER
+ _InterlockedIncrement(&shared_owners_);
+#else
+ ++shared_owners_;
+#endif
}
void
shared_count::release_shared()
{
- if (decrement(shared_owners_) == -1)
+#ifdef _MSC_VER
+ if (_InterlockedDecrement(&shared_owners_) == -1)
+#else
+ if (--shared_owners_ == -1)
+#endif
{
on_zero_shared();
delete this;
diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp
index 2f4bcecda8f3..d4ce470d56f3 100644
--- a/source/Utility/StringExtractor.cpp
+++ b/source/Utility/StringExtractor.cpp
@@ -168,10 +168,68 @@ StringExtractor::GetU32 (uint32_t fail_value, int base)
{
char *end = NULL;
const char *start = m_packet.c_str();
- const char *uint_cstr = start + m_index;
- uint32_t result = ::strtoul (uint_cstr, &end, base);
+ const char *cstr = start + m_index;
+ uint32_t result = ::strtoul (cstr, &end, base);
- if (end && end != uint_cstr)
+ if (end && end != cstr)
+ {
+ m_index = end - start;
+ return result;
+ }
+ }
+ return fail_value;
+}
+
+int32_t
+StringExtractor::GetS32 (int32_t fail_value, int base)
+{
+ if (m_index < m_packet.size())
+ {
+ char *end = NULL;
+ const char *start = m_packet.c_str();
+ const char *cstr = start + m_index;
+ int32_t result = ::strtol (cstr, &end, base);
+
+ if (end && end != cstr)
+ {
+ m_index = end - start;
+ return result;
+ }
+ }
+ return fail_value;
+}
+
+
+uint64_t
+StringExtractor::GetU64 (uint64_t fail_value, int base)
+{
+ if (m_index < m_packet.size())
+ {
+ char *end = NULL;
+ const char *start = m_packet.c_str();
+ const char *cstr = start + m_index;
+ uint64_t result = ::strtoull (cstr, &end, base);
+
+ if (end && end != cstr)
+ {
+ m_index = end - start;
+ return result;
+ }
+ }
+ return fail_value;
+}
+
+int64_t
+StringExtractor::GetS64 (int64_t fail_value, int base)
+{
+ if (m_index < m_packet.size())
+ {
+ char *end = NULL;
+ const char *start = m_packet.c_str();
+ const char *cstr = start + m_index;
+ int64_t result = ::strtoll (cstr, &end, base);
+
+ if (end && end != cstr)
{
m_index = end - start;
return result;
@@ -371,6 +429,20 @@ StringExtractor::GetHexByteString (std::string &str)
return str.size();
}
+size_t
+StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
+ char terminator)
+{
+ str.clear();
+ char ch;
+ while ((ch = GetHexU8(0,false)) != '\0')
+ str.append(1, ch);
+ if (Peek() && *Peek() == terminator)
+ return str.size();
+ str.clear();
+ return str.size();
+}
+
bool
StringExtractor::GetNameColonValue (std::string &name, std::string &value)
{
diff --git a/source/Utility/StringExtractor.h b/source/Utility/StringExtractor.h
index 0ded3101fcca..2aab3b09f47e 100644
--- a/source/Utility/StringExtractor.h
+++ b/source/Utility/StringExtractor.h
@@ -101,9 +101,18 @@ public:
bool
GetNameColonValue (std::string &name, std::string &value);
+ int32_t
+ GetS32 (int32_t fail_value, int base = 0);
+
uint32_t
GetU32 (uint32_t fail_value, int base = 0);
+ int64_t
+ GetS64 (int64_t fail_value, int base = 0);
+
+ uint64_t
+ GetU64 (uint64_t fail_value, int base = 0);
+
uint32_t
GetHexMaxU32 (bool little_endian, uint32_t fail_value);
@@ -119,6 +128,10 @@ public:
size_t
GetHexByteString (std::string &str);
+ size_t
+ GetHexByteStringTerminatedBy (std::string &str,
+ char terminator);
+
const char *
Peek ()
{
diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp
index 7e06a0f59bc9..6e32481ccc50 100644
--- a/source/Utility/StringExtractorGDBRemote.cpp
+++ b/source/Utility/StringExtractorGDBRemote.cpp
@@ -94,6 +94,9 @@ StringExtractorGDBRemote::GetServerPacketType () const
else if (PACKET_STARTS_WITH ("QSetSTDERR:")) return eServerPacketType_QSetSTDERR;
else if (PACKET_STARTS_WITH ("QSetWorkingDir:")) return eServerPacketType_QSetWorkingDir;
break;
+ case 'L':
+ if (PACKET_STARTS_WITH ("QLaunchArch:")) return eServerPacketType_QLaunchArch;
+ break;
}
break;
@@ -120,14 +123,21 @@ StringExtractorGDBRemote::GetServerPacketType () const
if (PACKET_MATCHES ("qHostInfo")) return eServerPacketType_qHostInfo;
break;
+ case 'K':
+ if (PACKET_STARTS_WITH ("qKillSpawnedProcess")) return eServerPacketType_qKillSpawnedProcess;
+ break;
+
case 'L':
- if (PACKET_MATCHES ("qLaunchGDBServer")) return eServerPacketType_qLaunchGDBServer;
+ if (PACKET_STARTS_WITH ("qLaunchGDBServer")) return eServerPacketType_qLaunchGDBServer;
if (PACKET_MATCHES ("qLaunchSuccess")) return eServerPacketType_qLaunchSuccess;
break;
case 'P':
- if (PACKET_STARTS_WITH ("qProcessInfoPID:")) return eServerPacketType_qProcessInfoPID;
+ if (PACKET_STARTS_WITH ("qProcessInfoPID:")) return eServerPacketType_qProcessInfoPID;
+ if (PACKET_STARTS_WITH ("qPlatform_RunCommand:")) return eServerPacketType_qPlatform_RunCommand;
+ if (PACKET_STARTS_WITH ("qPlatform_IO_MkDir:")) return eServerPacketType_qPlatform_IO_MkDir;
break;
+
case 'S':
if (PACKET_STARTS_WITH ("qSpeedTest:")) return eServerPacketType_qSpeedTest;
@@ -138,6 +148,21 @@ StringExtractorGDBRemote::GetServerPacketType () const
break;
}
break;
+ case 'v':
+ if (PACKET_STARTS_WITH("vFile:"))
+ {
+ if (PACKET_STARTS_WITH("vFile:open:")) return eServerPacketType_vFile_Open;
+ else if (PACKET_STARTS_WITH("vFile:close:")) return eServerPacketType_vFile_Close;
+ else if (PACKET_STARTS_WITH("vFile:pread")) return eServerPacketType_vFile_pRead;
+ else if (PACKET_STARTS_WITH("vFile:pwrite")) return eServerPacketType_vFile_pWrite;
+ else if (PACKET_STARTS_WITH("vFile:size")) return eServerPacketType_vFile_Size;
+ else if (PACKET_STARTS_WITH("vFile:exists")) return eServerPacketType_vFile_Exists;
+ else if (PACKET_STARTS_WITH("vFile:stat")) return eServerPacketType_vFile_Stat;
+ else if (PACKET_STARTS_WITH("vFile:mode")) return eServerPacketType_vFile_Mode;
+ else if (PACKET_STARTS_WITH("vFile:MD5")) return eServerPacketType_vFile_MD5;
+
+ }
+ break;
}
return eServerPacketType_unimplemented;
}
@@ -180,3 +205,19 @@ StringExtractorGDBRemote::GetError ()
}
return 0;
}
+
+size_t
+StringExtractorGDBRemote::GetEscapedBinaryData (std::string &str)
+{
+ str.clear();
+ char ch;
+ while (GetBytesLeft())
+ {
+ ch = GetChar();
+ if (ch == 0x7d)
+ ch = (GetChar() ^ 0x20);
+ str.append(1,ch);
+ }
+ return str.size();
+}
+
diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h
index 5a24d894b105..fe500ecda5d4 100644
--- a/source/Utility/StringExtractorGDBRemote.h
+++ b/source/Utility/StringExtractorGDBRemote.h
@@ -53,17 +53,30 @@ public:
eServerPacketType_qGroupName,
eServerPacketType_qHostInfo,
eServerPacketType_qLaunchGDBServer,
+ eServerPacketType_qKillSpawnedProcess,
eServerPacketType_qLaunchSuccess,
eServerPacketType_qProcessInfoPID,
eServerPacketType_qSpeedTest,
eServerPacketType_qUserName,
eServerPacketType_QEnvironment,
+ eServerPacketType_QLaunchArch,
eServerPacketType_QSetDisableASLR,
eServerPacketType_QSetSTDIN,
eServerPacketType_QSetSTDOUT,
eServerPacketType_QSetSTDERR,
eServerPacketType_QSetWorkingDir,
- eServerPacketType_QStartNoAckMode
+ eServerPacketType_QStartNoAckMode,
+ eServerPacketType_qPlatform_RunCommand,
+ eServerPacketType_qPlatform_IO_MkDir,
+ eServerPacketType_vFile_Open,
+ eServerPacketType_vFile_Close,
+ eServerPacketType_vFile_pRead,
+ eServerPacketType_vFile_pWrite,
+ eServerPacketType_vFile_Size,
+ eServerPacketType_vFile_Mode,
+ eServerPacketType_vFile_Exists,
+ eServerPacketType_vFile_MD5,
+ eServerPacketType_vFile_Stat
};
ServerPacketType
@@ -98,6 +111,10 @@ public:
// digits. Otherwise the error encoded in XX is returned.
uint8_t
GetError();
+
+ size_t
+ GetEscapedBinaryData (std::string &str);
+
};
#endif // utility_StringExtractorGDBRemote_h_
diff --git a/source/lldb-log.cpp b/source/lldb-log.cpp
index c53fa56ef019..5e1dc3a54e8a 100644
--- a/source/lldb-log.cpp
+++ b/source/lldb-log.cpp
@@ -126,6 +126,7 @@ lldb_private::DisableLog (const char **categories, Stream *feedback_strm)
else if (0 == ::strncasecmp(arg, "expr", 4)) flag_bits &= ~LIBLLDB_LOG_EXPRESSIONS;
else if (0 == ::strncasecmp(arg, "object", 6)) flag_bits &= ~LIBLLDB_LOG_OBJECT;
else if (0 == ::strcasecmp(arg, "process")) flag_bits &= ~LIBLLDB_LOG_PROCESS;
+ else if (0 == ::strcasecmp(arg, "platform")) flag_bits &= ~LIBLLDB_LOG_PLATFORM;
else if (0 == ::strcasecmp(arg, "script")) flag_bits &= ~LIBLLDB_LOG_SCRIPT;
else if (0 == ::strcasecmp(arg, "state")) flag_bits &= ~LIBLLDB_LOG_STATE;
else if (0 == ::strcasecmp(arg, "step")) flag_bits &= ~LIBLLDB_LOG_STEP;
@@ -190,29 +191,30 @@ lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const ch
else if (0 == ::strcasecmp(arg, "api")) flag_bits |= LIBLLDB_LOG_API;
else if (0 == ::strncasecmp(arg, "break", 5)) flag_bits |= LIBLLDB_LOG_BREAKPOINTS;
else if (0 == ::strcasecmp(arg, "commands")) flag_bits |= LIBLLDB_LOG_COMMANDS;
+ else if (0 == ::strncasecmp(arg, "commu", 5)) flag_bits |= LIBLLDB_LOG_COMMUNICATION;
+ else if (0 == ::strncasecmp(arg, "conn", 4)) flag_bits |= LIBLLDB_LOG_CONNECTION;
else if (0 == ::strcasecmp(arg, "default")) flag_bits |= LIBLLDB_LOG_DEFAULT;
else if (0 == ::strcasecmp(arg, "dyld")) flag_bits |= LIBLLDB_LOG_DYNAMIC_LOADER;
else if (0 == ::strncasecmp(arg, "event", 5)) flag_bits |= LIBLLDB_LOG_EVENTS;
else if (0 == ::strncasecmp(arg, "expr", 4)) flag_bits |= LIBLLDB_LOG_EXPRESSIONS;
+ else if (0 == ::strncasecmp(arg, "host", 4)) flag_bits |= LIBLLDB_LOG_HOST;
+ else if (0 == ::strncasecmp(arg, "mmap", 4)) flag_bits |= LIBLLDB_LOG_MMAP;
+ else if (0 == ::strncasecmp(arg, "module", 6)) flag_bits |= LIBLLDB_LOG_MODULES;
else if (0 == ::strncasecmp(arg, "object", 6)) flag_bits |= LIBLLDB_LOG_OBJECT;
+ else if (0 == ::strcasecmp(arg, "os")) flag_bits |= LIBLLDB_LOG_OS;
+ else if (0 == ::strcasecmp(arg, "platform")) flag_bits |= LIBLLDB_LOG_PLATFORM;
else if (0 == ::strcasecmp(arg, "process")) flag_bits |= LIBLLDB_LOG_PROCESS;
else if (0 == ::strcasecmp(arg, "script")) flag_bits |= LIBLLDB_LOG_SCRIPT;
else if (0 == ::strcasecmp(arg, "state")) flag_bits |= LIBLLDB_LOG_STATE;
else if (0 == ::strcasecmp(arg, "step")) flag_bits |= LIBLLDB_LOG_STEP;
- else if (0 == ::strcasecmp(arg, "thread")) flag_bits |= LIBLLDB_LOG_THREAD;
+ else if (0 == ::strncasecmp(arg, "symbol", 6)) flag_bits |= LIBLLDB_LOG_SYMBOLS;
else if (0 == ::strcasecmp(arg, "target")) flag_bits |= LIBLLDB_LOG_TARGET;
- 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 == ::strncasecmp(arg, "temp", 4)) flag_bits |= LIBLLDB_LOG_TEMPORARY;
- else if (0 == ::strncasecmp(arg, "comm", 4)) flag_bits |= LIBLLDB_LOG_COMMUNICATION;
- else if (0 == ::strncasecmp(arg, "conn", 4)) flag_bits |= LIBLLDB_LOG_CONNECTION;
- else if (0 == ::strncasecmp(arg, "host", 4)) flag_bits |= LIBLLDB_LOG_HOST;
- else if (0 == ::strncasecmp(arg, "unwind", 6)) flag_bits |= LIBLLDB_LOG_UNWIND;
+ else if (0 == ::strcasecmp(arg, "thread")) flag_bits |= LIBLLDB_LOG_THREAD;
else if (0 == ::strncasecmp(arg, "types", 5)) flag_bits |= LIBLLDB_LOG_TYPES;
- else if (0 == ::strncasecmp(arg, "symbol", 6)) flag_bits |= LIBLLDB_LOG_SYMBOLS;
- 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 == ::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
{
feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
@@ -237,12 +239,18 @@ lldb_private::ListLogCategories (Stream *strm)
" api - enable logging of API calls and return values\n"
" break - log breakpoints\n"
" commands - log command argument parsing\n"
+ " communication - log communication activities\n"
+ " connection - log connection details\n"
" default - enable the default set of logging categories for liblldb\n"
" dyld - log shared library related activities\n"
" events - log broadcaster, listener and event queue activities\n"
" expr - log expressions\n"
- " object - log object construction/destruction for important objects\n"
+ " host - log host activities\n"
+ " mmap - log mmap related activities\n"
" module - log module activities such as when modules are created, detroyed, 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"
" process - log process events and activities\n"
" script - log events about the script interpreter\n"
" state - log private and public process state changes\n"
diff --git a/source/lldb.cpp b/source/lldb.cpp
index 1ac03f4f190c..c69563773915 100644
--- a/source/lldb.cpp
+++ b/source/lldb.cpp
@@ -42,6 +42,8 @@
#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"
#ifndef LLDB_DISABLE_PYTHON
#include "Plugins/OperatingSystem/Python/OperatingSystemPython.h"
@@ -62,7 +64,7 @@
#include "Plugins/Process/mach-core/ProcessMachCore.h"
-#if defined(__linux__) or defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__)
#include "Plugins/Process/elf-core/ProcessElfCore.h"
#endif
@@ -113,6 +115,7 @@ lldb_private::Initialize ()
DynamicLoaderPOSIXDYLD::Initialize ();
PlatformFreeBSD::Initialize();
PlatformLinux::Initialize();
+ PlatformWindows::Initialize();
SymbolFileDWARFDebugMap::Initialize();
ItaniumABILanguageRuntime::Initialize();
#ifndef LLDB_DISABLE_PYTHON
@@ -147,7 +150,7 @@ lldb_private::Initialize ()
ProcessFreeBSD::Initialize();
#endif
-#if defined(__linux__) or defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__)
ProcessElfCore::Initialize();
#endif
//----------------------------------------------------------------------
@@ -180,7 +183,6 @@ lldb_private::Terminate ()
// Terminate and unload and loaded system or user LLDB plug-ins
PluginManager::Terminate();
-
ABIMacOSX_i386::Terminate();
ABIMacOSX_arm::Terminate();
ABISysV_x86_64::Terminate();
@@ -197,6 +199,7 @@ lldb_private::Terminate ()
DynamicLoaderPOSIXDYLD::Terminate ();
PlatformFreeBSD::Terminate();
PlatformLinux::Terminate();
+ PlatformWindows::Terminate();
SymbolFileDWARFDebugMap::Terminate();
ItaniumABILanguageRuntime::Terminate();
#ifndef LLDB_DISABLE_PYTHON
@@ -229,7 +232,7 @@ lldb_private::Terminate ()
ProcessFreeBSD::Terminate();
#endif
-#if defined(__linux__) or defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__)
ProcessElfCore::Terminate();
#endif
ProcessGDBRemote::Terminate();
@@ -407,7 +410,7 @@ lldb_private::NameMatches (const char *name,
llvm::StringRef match_sref(match);
switch (match_type)
{
- case eNameMatchIgnore:
+ case eNameMatchIgnore: // This case cannot occur: tested before
return true;
case eNameMatchEquals: return name_sref == match_sref;
case eNameMatchContains: return name_sref.find (match_sref) != llvm::StringRef::npos;
diff --git a/tools/driver/Driver.cpp b/tools/driver/Driver.cpp
index 875adc22283a..e2742425dd4c 100644
--- a/tools/driver/Driver.cpp
+++ b/tools/driver/Driver.cpp
@@ -9,19 +9,15 @@
#include "Driver.h"
-#include <getopt.h>
-#include <libgen.h>
-#include <sys/ioctl.h>
-#include <termios.h>
-#include <unistd.h>
+#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <fcntl.h>
-#include <inttypes.h>
#include <string>
+#include <thread>
#include "IOChannel.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBCommandInterpreter.h"
@@ -99,13 +95,21 @@ static OptionDefinition g_options[] =
"extensions have been implemented." },
{ LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone,
"Tells the debugger to print out extra information for debugging itself." },
+ { LLDB_3_TO_5, false, "source-quietly" , 'b', no_argument , 0, eArgTypeNone,
+ "Tells the debugger to print out extra information for debugging itself." },
{ LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename,
- "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
+ "Tells the debugger to read in and execute the lldb commands in the given file, after any file provided on the command line has been loaded." },
+ { LLDB_3_TO_5, false, "one-line" , 'o', required_argument, 0, eArgTypeNone,
+ "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded." },
+ { LLDB_3_TO_5, false, "source-before-file" , 'S', required_argument, 0, eArgTypeFilename,
+ "Tells the debugger to read in and execute the lldb commands in the given file, before any file provided on the command line has been loaded." },
+ { LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone,
+ "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." },
{ LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone,
"Tells the debugger to open source files using the host's \"external editor\" mechanism." },
{ LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone,
"Do not automatically parse any '.lldbinit' files." },
- { LLDB_3_TO_5, false, "no-use-colors" , 'o', no_argument , 0, eArgTypeNone,
+ { LLDB_3_TO_5, false, "no-use-colors" , 'X', no_argument , 0, eArgTypeNone,
"Do not use colors." },
{ LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone,
"Prints out the path to the lldb.py file for this version of lldb." },
@@ -147,7 +151,9 @@ Driver::CloseIOChannelFile ()
// Write an End of File sequence to the file descriptor to ensure any
// read functions can exit.
char eof_str[] = "\x04";
- ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
+ int mfd = m_editline_pty.GetMasterFileDescriptor();
+ if (mfd != -1)
+ ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
m_editline_pty.CloseMasterFileDescriptor();
@@ -341,6 +347,15 @@ ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
indent_level -= 5;
+ fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed from left to right in order, "
+ "\n%*swith the source files and commands interleaved. The same is true of the \"-S\" and \"-O\" options."
+ "\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out."
+ "\n%*sThe order of the file specifiers (\"-c\", \"-f\", etc.) is not significant in this regard.\n\n",
+ indent_level, "",
+ indent_level, "",
+ indent_level, "",
+ indent_level, "");
+
fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
"\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
"\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
@@ -390,8 +405,10 @@ Driver::OptionData::OptionData () :
m_script_lang (lldb::eScriptLanguageDefault),
m_core_file (),
m_crash_log (),
- m_source_command_files (),
+ m_initial_commands (),
+ m_after_file_commands (),
m_debug_mode (false),
+ m_source_quietly(false),
m_print_version (false),
m_print_python_path (false),
m_print_help (false),
@@ -412,8 +429,10 @@ Driver::OptionData::Clear ()
{
m_args.clear ();
m_script_lang = lldb::eScriptLanguageDefault;
- m_source_command_files.clear ();
+ m_initial_commands.clear ();
+ m_after_file_commands.clear ();
m_debug_mode = false;
+ m_source_quietly = false;
m_print_help = false;
m_print_version = false;
m_print_python_path = false;
@@ -424,6 +443,34 @@ Driver::OptionData::Clear ()
}
void
+Driver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error)
+{
+ std::vector<std::pair<bool, std::string> > *command_set;
+ if (before_file)
+ command_set = &(m_initial_commands);
+ else
+ command_set = &(m_after_file_commands);
+
+ if (is_file)
+ {
+ SBFileSpec file(command);
+ if (file.Exists())
+ command_set->push_back (std::pair<bool, std::string> (true, optarg));
+ else if (file.ResolveExecutableLocation())
+ {
+ char final_path[PATH_MAX];
+ file.GetPath (final_path, sizeof(final_path));
+ std::string path_str (final_path);
+ command_set->push_back (std::pair<bool, std::string> (true, path_str));
+ }
+ else
+ error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
+ }
+ else
+ command_set->push_back (std::pair<bool, std::string> (false, optarg));
+}
+
+void
Driver::ResetOptionValues ()
{
m_option_data.Clear ();
@@ -451,18 +498,60 @@ Driver::GetScriptLanguage() const
return m_option_data.m_script_lang;
}
-size_t
-Driver::GetNumSourceCommandFiles () const
-{
- return m_option_data.m_source_command_files.size();
-}
-
-const char *
-Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
+void
+Driver::ExecuteInitialCommands (bool before_file)
{
- if (idx < m_option_data.m_source_command_files.size())
- return m_option_data.m_source_command_files[idx].c_str();
- return NULL;
+ size_t num_commands;
+ std::vector<std::pair<bool, std::string> > *command_set;
+ if (before_file)
+ command_set = &(m_option_data.m_initial_commands);
+ else
+ command_set = &(m_option_data.m_after_file_commands);
+
+ num_commands = command_set->size();
+ SBCommandReturnObject result;
+ bool old_async = GetDebugger().GetAsync();
+ GetDebugger().SetAsync(false);
+ for (size_t idx = 0; idx < num_commands; idx++)
+ {
+ bool is_file = (*command_set)[idx].first;
+ const char *command = (*command_set)[idx].second.c_str();
+ char command_string[PATH_MAX * 2];
+ const bool dump_stream_only_if_no_immediate = true;
+ const char *executed_command = command;
+ if (is_file)
+ {
+ ::snprintf (command_string, sizeof(command_string), "command source '%s'", command);
+ executed_command = command_string;
+ }
+
+ m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false);
+ if (!m_option_data.m_source_quietly || result.Succeeded() == false)
+ {
+ const size_t output_size = result.GetOutputSize();
+ if (output_size > 0)
+ m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
+ const size_t error_size = result.GetErrorSize();
+ if (error_size > 0)
+ m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
+ }
+
+ if (result.Succeeded() == false)
+ {
+ char error_buffer[1024];
+ size_t error_size;
+ const char *type = before_file ? "before file" : "after_file";
+ if (is_file)
+ error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command file: '%s' failed.\n", type, command);
+ else
+ error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command: '%s' failed.\n", type, command);
+
+ m_io_channel_ap->OutWrite(error_buffer, error_size, NO_ASYNC);
+ break;
+ }
+ result.Clear();
+ }
+ GetDebugger().SetAsync(old_async);
}
bool
@@ -478,7 +567,7 @@ Driver::GetDebugMode() const
// if the user only wanted help or version information.
SBError
-Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
+Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting)
{
ResetOptionValues ();
@@ -623,7 +712,7 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
m_debugger.SkipAppInitFiles (true);
break;
- case 'o':
+ case 'X':
m_debugger.SetUseColor (false);
break;
@@ -658,6 +747,10 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
m_option_data.m_debug_mode = true;
break;
+ case 'q':
+ m_option_data.m_source_quietly = true;
+ break;
+
case 'n':
m_option_data.m_process_name = optarg;
break;
@@ -676,22 +769,17 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
}
break;
case 's':
- {
- SBFileSpec file(optarg);
- if (file.Exists())
- m_option_data.m_source_command_files.push_back (optarg);
- else if (file.ResolveExecutableLocation())
- {
- char final_path[PATH_MAX];
- file.GetPath (final_path, sizeof(final_path));
- std::string path_str (final_path);
- m_option_data.m_source_command_files.push_back (path_str);
- }
- else
- error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
- }
+ m_option_data.AddInitialCommand(optarg, false, true, error);
+ break;
+ case 'o':
+ m_option_data.AddInitialCommand(optarg, false, false, error);
+ break;
+ case 'S':
+ m_option_data.AddInitialCommand(optarg, true, true, error);
+ break;
+ case 'O':
+ m_option_data.AddInitialCommand(optarg, true, false, error);
break;
-
default:
m_option_data.m_print_help = true;
error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
@@ -712,12 +800,12 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
if (error.Fail() || m_option_data.m_print_help)
{
ShowUsage (out_fh, g_options, m_option_data);
- exit = true;
+ exiting = true;
}
else if (m_option_data.m_print_version)
{
::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
- exit = true;
+ exiting = true;
}
else if (m_option_data.m_print_python_path)
{
@@ -735,7 +823,7 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
}
else
::fprintf (out_fh, "<COULD NOT FIND PATH>\n");
- exit = true;
+ exiting = true;
}
else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID)
{
@@ -1221,6 +1309,12 @@ Driver::EditLineInputReaderCallback
void
Driver::MainLoop ()
{
+#if defined(_MSC_VER)
+ m_editline_slave_fh = stdin;
+ FILE *editline_output_slave_fh = stdout;
+ lldb_utility::PseudoTerminal editline_output_pty;
+#else
+
char error_str[1024];
if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
{
@@ -1281,6 +1375,7 @@ Driver::MainLoop ()
::setbuf (editline_output_slave_fh, NULL);
}
}
+#endif
// struct termios stdin_termios;
@@ -1322,6 +1417,7 @@ Driver::MainLoop ()
m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
+#if !defined (_MSC_VER)
SBCommunication out_comm_2("driver.editline_output");
out_comm_2.SetCloseOnEOF (false);
out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
@@ -1332,6 +1428,7 @@ Driver::MainLoop ()
::fprintf (stderr, "error: failed to start libedit output read thread");
exit (5);
}
+#endif
struct winsize window_size;
@@ -1400,42 +1497,15 @@ Driver::MainLoop ()
}
// Now we handle options we got from the command line
- char command_string[PATH_MAX * 2];
- const size_t num_source_command_files = GetNumSourceCommandFiles();
- const bool dump_stream_only_if_no_immediate = true;
- if (num_source_command_files > 0)
- {
- for (size_t i=0; i < num_source_command_files; ++i)
- {
- const char *command_file = GetSourceCommandFileAtIndex(i);
- ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
- m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
- if (GetDebugMode())
- {
- result.PutError (m_debugger.GetErrorFileHandle());
- result.PutOutput (m_debugger.GetOutputFileHandle());
- }
-
- // if the command sourcing generated an error - dump the result object
- if (result.Succeeded() == false)
- {
- const size_t output_size = result.GetOutputSize();
- if (output_size > 0)
- m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
- const size_t error_size = result.GetErrorSize();
- if (error_size > 0)
- m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
- }
-
- result.Clear();
- }
- }
-
+ // First source in the commands specified to be run before the file arguments are processed.
+ ExecuteInitialCommands(true);
+
// Was there a core file specified?
std::string core_file_spec("");
if (!m_option_data.m_core_file.empty())
core_file_spec.append("--core ").append(m_option_data.m_core_file);
+ char command_string[PATH_MAX * 2];
const size_t num_args = m_option_data.m_args.size();
if (num_args > 0)
{
@@ -1487,6 +1557,9 @@ Driver::MainLoop ()
result.PutError(m_debugger.GetErrorFileHandle());
result.PutOutput(m_debugger.GetOutputFileHandle());
}
+
+ // Now execute the commands specified for after the file arguments are processed.
+ ExecuteInitialCommands(false);
SBEvent event;
@@ -1597,9 +1670,11 @@ Driver::MainLoop ()
master_out_comm.Disconnect();
master_out_comm.ReadThreadStop();
+#if !defined(_MSC_VER)
out_comm_2.SetReadThreadBytesReceivedCallback(NULL, NULL);
out_comm_2.Disconnect();
out_comm_2.ReadThreadStop();
+#endif
editline_output_pty.CloseMasterFileDescriptor();
reset_stdin_termios();
@@ -1714,15 +1789,15 @@ main (int argc, char const *argv[], const char *envp[])
{
Driver driver;
- bool exit = false;
- SBError error (driver.ParseArgs (argc, argv, stdout, exit));
+ bool exiting = false;
+ SBError error (driver.ParseArgs (argc, argv, stdout, exiting));
if (error.Fail())
{
const char *error_cstr = error.GetCString ();
if (error_cstr)
::fprintf (stderr, "error: %s\n", error_cstr);
}
- else if (!exit)
+ else if (!exiting)
{
driver.MainLoop ();
}
diff --git a/tools/driver/Driver.h b/tools/driver/Driver.h
index 2a4a27df4cdc..dcfd5ed11cd1 100644
--- a/tools/driver/Driver.h
+++ b/tools/driver/Driver.h
@@ -10,6 +10,7 @@
#ifndef lldb_Driver_h_
#define lldb_Driver_h_
+#include "Platform.h"
#include "lldb/Utility/PseudoTerminal.h"
#include <set>
@@ -83,12 +84,9 @@ public:
lldb::ScriptLanguage
GetScriptLanguage() const;
- size_t
- GetNumSourceCommandFiles () const;
-
- const char *
- GetSourceCommandFileAtIndex (uint32_t idx) const;
-
+ void
+ ExecuteInitialCommands (bool before_file);
+
bool
GetDebugMode() const;
@@ -102,14 +100,19 @@ public:
void
Clear();
+ void
+ AddInitialCommand (const char *command, bool before_file, bool is_file, lldb::SBError &error);
+
//static OptionDefinition m_cmd_option_table[];
std::vector<std::string> m_args;
lldb::ScriptLanguage m_script_lang;
std::string m_core_file;
std::string m_crash_log;
- std::vector<std::string> m_source_command_files;
+ std::vector<std::pair<bool,std::string> > m_initial_commands;
+ std::vector<std::pair<bool,std::string> > m_after_file_commands;
bool m_debug_mode;
+ bool m_source_quietly;
bool m_print_version;
bool m_print_python_path;
bool m_print_help;
diff --git a/tools/driver/ELWrapper.cpp b/tools/driver/ELWrapper.cpp
new file mode 100644
index 000000000000..258f47e5169c
--- /dev/null
+++ b/tools/driver/ELWrapper.cpp
@@ -0,0 +1,422 @@
+//===-- ELWrapper.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// this file is only relevant for Visual C++
+#if defined( _MSC_VER )
+
+#include "lldb/Host/windows/windows.h"
+
+#include "ELWrapper.h"
+#include <vector>
+#include <assert.h>
+
+// index one of the variable arguments
+// presuming "(EditLine *el, ..." is first in the argument list
+#define GETARG( X ) ( (void* ) *( ( (int**) &el ) + ((X) + 2) ) )
+
+// edit line EL_ADDFN function pointer type
+typedef unsigned char (*el_addfn_func)(EditLine *e, int ch);
+
+// edit line wrapper binding container
+struct el_binding
+{
+ //
+ const char *name;
+ const char *help;
+ // function pointer to callback routine
+ el_addfn_func func;
+ // ascii key this function is bound to
+ const char *key;
+};
+
+// stored key bindings
+static std::vector<el_binding*> _bindings;
+
+//TODO: this should infact be related to the exact edit line context we create
+static void *clientData = NULL;
+
+// store the current prompt string
+// default to what we expect to receive anyway
+static const char *_prompt = "(lldb) ";
+
+#if !defined( _WIP_INPUT_METHOD )
+
+static char *
+el_get_s (char *buffer, int chars)
+{
+ return gets_s(buffer, chars);
+}
+#else
+
+static void
+con_output (char _in)
+{
+ HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE );
+ DWORD written = 0;
+ // get the cursor position
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo( hout, &info );
+ // output this char
+ WriteConsoleOutputCharacterA( hout, &_in, 1, info.dwCursorPosition, &written );
+ // advance cursor position
+ info.dwCursorPosition.X++;
+ SetConsoleCursorPosition( hout, info.dwCursorPosition );
+}
+
+static void
+con_backspace (void)
+{
+ HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE );
+ DWORD written = 0;
+ // get cursor position
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo( hout, &info );
+ // nudge cursor backwards
+ info.dwCursorPosition.X--;
+ SetConsoleCursorPosition( hout, info.dwCursorPosition );
+ // blank out the last character
+ WriteConsoleOutputCharacterA( hout, " ", 1, info.dwCursorPosition, &written );
+}
+
+static void
+con_return (void)
+{
+ HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE );
+ DWORD written = 0;
+ // get cursor position
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo( hout, &info );
+ // move onto the new line
+ info.dwCursorPosition.X = 0;
+ info.dwCursorPosition.Y++;
+ SetConsoleCursorPosition( hout, info.dwCursorPosition );
+}
+
+static bool
+runBind (char _key)
+{
+ for ( int i=0; i<_bindings.size(); i++ )
+ {
+ el_binding *bind = _bindings[i];
+ if ( bind->key[0] == _key )
+ {
+ bind->func( (EditLine*) -1, _key );
+ return true;
+ }
+ }
+ return false;
+}
+
+// replacement get_s which is EL_BIND aware
+static char *
+el_get_s (char *buffer, int chars)
+{
+ //
+ char *head = buffer;
+ //
+ for ( ;; Sleep( 10 ) )
+ {
+ //
+ INPUT_RECORD _record;
+ //
+ DWORD _read = 0;
+ if ( ReadConsoleInputA( GetStdHandle( STD_INPUT_HANDLE ), &_record, 1, &_read ) == FALSE )
+ break;
+ // if we didnt read a key
+ if ( _read == 0 )
+ continue;
+ // only interested in key events
+ if ( _record.EventType != KEY_EVENT )
+ continue;
+ // is the key down
+ if (! _record.Event.KeyEvent.bKeyDown )
+ continue;
+ // read the ascii key character
+ char _key = _record.Event.KeyEvent.uChar.AsciiChar;
+ // non ascii conformant key press
+ if ( _key == 0 )
+ {
+ // check the scan code
+ // if VK_UP scroll back through history
+ // if VK_DOWN scroll forward through history
+ continue;
+ }
+ // try to execute any bind this key may have
+ if ( runBind( _key ) )
+ continue;
+ // if we read a return key
+ if ( _key == '\n' || _key == '\r' )
+ {
+ con_return( );
+ break;
+ }
+ // key is backspace
+ if ( _key == 0x8 )
+ {
+ // avoid deleting past beginning
+ if ( head > buffer )
+ {
+ con_backspace( );
+ head--;
+ }
+ continue;
+ }
+
+ // add this key to the input buffer
+ if ( (head-buffer) < (chars-1) )
+ {
+ con_output( _key );
+ *(head++) = _key;
+ }
+ }
+ // insert end of line character
+ *head = '\0';
+
+ return buffer;
+}
+#endif
+
+// edit line initalise
+EditLine *
+el_init (const char *, FILE *, FILE *, FILE *)
+{
+ //
+ SetConsoleTitleA( "lldb" );
+ // return dummy handle
+ return (EditLine*) -1;
+}
+
+const char *
+el_gets (EditLine *el, int *length)
+{
+ // print the prompt if we have one
+ if ( _prompt != NULL )
+ printf( _prompt );
+ // create a buffer for the user input
+ char *buffer = new char[ MAX_PATH ];
+ // try to get user input string
+ if ( el_get_s( buffer, MAX_PATH ) )
+ {
+ // get the string length in 'length'
+ while ( buffer[ *length ] != '\0' )
+ (*length)++;
+ // return the input buffer
+ // remember that this memory has the be free'd somewhere
+ return buffer;
+ }
+ else
+ {
+ // on error
+ delete [] buffer;
+ return NULL;
+ }
+}
+
+int
+el_set (EditLine *el, int code, ...)
+{
+ int **arg = (int**) &el;
+ //
+ switch ( code )
+ {
+ // edit line set prompt message
+ case ( EL_PROMPT ):
+ {
+ // EL_PROMPT, char *(*f)( EditLine *)
+ // define a prompt printing function as 'f', which is to return a string that
+ // contains the prompt.
+
+ // get the function pointer from the arg list
+ void *func_vp = (void*) *(arg+2);
+ // cast to suitable prototype
+ const char* (*func_fp)(EditLine*) = (const char*(*)(EditLine *)) func_vp;
+ // call to get the prompt as a string
+ _prompt = func_fp( el );
+ }
+ break;
+ case ( EL_EDITOR ):
+ {
+ // EL_EDITOR, const char *mode
+ // set editing mode to "emacs" or "vi"
+ }
+ break;
+ case ( EL_HIST ):
+ {
+ // EL_HIST, History *(*fun)(History *, int op, ... ), const char *ptr
+ // defines which histroy function to use, which is usualy history(). Ptr should be the
+ // value returned by history_init().
+ }
+ break;
+ case ( EL_ADDFN ):
+ {
+ // EL_ADDFN, const char *name, const char *help, unsigned char (*func)(EditLine *e, int ch)
+ // add a user defined function, func), referred to as 'name' which is invoked when a key which is bound to 'name' is
+ // entered. 'help' is a description of 'name'. at involcation time, 'ch' is the key which caused the invocation. the
+ // return value of 'func()' should be one of:
+ // CC_NORM add a normal character
+ // CC_NEWLINE end of line was entered
+ // CC_EOF EOF was entered
+ // CC_ARGHACK expecting further command input as arguments, do nothing visually.
+ // CC_REFRESH refresh display.
+ // CC_REFRESH_BEEP refresh display and beep.
+ // CC_CURSOR cursor moved so update and perform CC_REFRESH
+ // CC_REDISPLAY redisplay entire input line. this is usefull if a key binding outputs extra information.
+ // CC_ERROR an error occured. beep and flush tty.
+ // CC_FATAL fatal error, reset tty to known state.
+
+ el_binding *binding = new el_binding;
+ binding->name = (const char *) GETARG( 0 );
+ binding->help = (const char *) GETARG( 1 );
+ binding->func = (el_addfn_func) GETARG( 2 );
+ binding->key = 0;
+ // add this to the bindings list
+ _bindings.push_back( binding );
+ }
+ break;
+ case ( EL_BIND ):
+ {
+ // EL_BIND, const char *, ..., NULL
+ // perform the BIND buildin command. Refer to editrc(5) for more information.
+
+ const char *name = (const char*) GETARG( 1 );
+
+ for ( int i=0; i<_bindings.size(); i++ )
+ {
+ el_binding *bind = _bindings[i];
+ if ( strcmp( bind->name, name ) == 0 )
+ {
+ bind->key = (const char *) GETARG( 0 );
+ break;
+ }
+ }
+
+ }
+ break;
+ case ( EL_CLIENTDATA ):
+ {
+ clientData = GETARG( 0 );
+ }
+ break;
+ default:
+ assert( !"Not Implemented!" );
+ }
+ return 0;
+}
+
+void
+el_end (EditLine *el)
+{
+ assert( !"Not implemented!" );
+}
+
+void
+el_reset (EditLine *)
+{
+ assert( !"Not implemented!" );
+}
+
+int
+el_getc (EditLine *, char *)
+{
+ assert( !"Not implemented!" );
+ return 0;
+}
+
+void
+el_push (EditLine *, char *)
+{
+ assert( !"Not implemented!" );
+}
+
+void
+el_beep (EditLine *)
+{
+ Beep( 1000, 500 );
+}
+
+int
+el_parse (EditLine *, int, const char **)
+{
+ assert( !"Not implemented!" );
+ return 0;
+}
+
+int
+el_get (EditLine *el, int code, ...)
+{
+ switch ( code )
+ {
+ case ( EL_CLIENTDATA ):
+ {
+ void **dout = (void**) GETARG( 0 );
+ *dout = clientData;
+ }
+ break;
+ default:
+ assert( !"Not implemented!" );
+ }
+ return 0;
+}
+
+int
+el_source (EditLine *el, const char *file)
+{
+ // init edit line by reading the contents of 'file'
+ // nothing to do here on windows...
+ return 0;
+}
+
+void
+el_resize (EditLine *)
+{
+ assert( !"Not implemented!" );
+}
+
+const LineInfo *
+el_line (EditLine *el)
+{
+ assert( !"Not implemented!" );
+ return 0;
+}
+
+int
+el_insertstr (EditLine *, const char *)
+{
+ assert( !"Not implemented!" );
+ return 0;
+}
+
+void
+el_deletestr (EditLine *, int)
+{
+ assert( !"Not implemented!" );
+}
+
+History *
+history_init (void)
+{
+ // return dummy handle
+ return (History*) -1;
+}
+
+void
+history_end (History *)
+{
+ assert( !"Not implemented!" );
+}
+
+int
+history (History *, HistEvent *, int op, ...)
+{
+ // perform operation 'op' on the history list with optional argumetns as needed by
+ // the operation.
+ return 0;
+}
+
+#endif
diff --git a/tools/driver/ELWrapper.h b/tools/driver/ELWrapper.h
new file mode 100644
index 000000000000..a30182d948b1
--- /dev/null
+++ b/tools/driver/ELWrapper.h
@@ -0,0 +1,122 @@
+//===-- ELWrapper.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include <stdio.h>
+
+// EditLine editor function return codes.
+// For user-defined function interface
+#define CC_NORM 0
+#define CC_NEWLINE 1
+#define CC_EOF 2
+#define CC_ARGHACK 3
+#define CC_REFRESH 4
+#define CC_CURSOR 5
+#define CC_ERROR 6
+#define CC_FATAL 7
+#define CC_REDISPLAY 8
+#define CC_REFRESH_BEEP 9
+
+// el_set/el_get parameters
+#define EL_PROMPT 0 // , el_pfunc_t
+#define EL_TERMINAL 1 // , const char *
+#define EL_EDITOR 2 // , const char *
+#define EL_SIGNAL 3 // , int);
+#define EL_BIND 4 // , const char *, ..., NULL
+#define EL_TELLTC 5 // , const char *, ..., NULL
+#define EL_SETTC 6 // , const char *, ..., NULL
+#define EL_ECHOTC 7 // , const char *, ..., NULL
+#define EL_SETTY 8 // , const char *, ..., NULL
+#define EL_ADDFN 9 // , const char *, const char *, el_func_t
+#define EL_HIST 10 // , hist_fun_t, const char *
+#define EL_EDITMODE 11 // , int
+#define EL_RPROMPT 12 // , el_pfunc_t
+#define EL_GETCFN 13 // , el_rfunc_t
+#define EL_CLIENTDATA 14 // , void *
+#define EL_UNBUFFERED 15 // , int
+#define EL_PREP_TERM 16 // , int
+#define EL_GETTC 17 // , const char *, ..., NULL
+#define EL_GETFP 18 // , int, FILE **
+#define EL_SETFP 19 // , int, FILE *
+#define EL_REFRESH 20 // , void
+
+#define EL_BUILTIN_GETCFN (NULL)
+
+// history defines
+#define H_FUNC 0 // , UTSL
+#define H_SETSIZE 1 // , const int
+#define H_GETSIZE 2 // , void
+#define H_FIRST 3 // , void
+#define H_LAST 4 // , void
+#define H_PREV 5 // , void
+#define H_NEXT 6 // , void
+#define H_CURR 8 // , const int
+#define H_SET 7 // , int
+#define H_ADD 9 // , const char *
+#define H_ENTER 10 // , const char *
+#define H_APPEND 11 // , const char *
+#define H_END 12 // , void
+#define H_NEXT_STR 13 // , const char *
+#define H_PREV_STR 14 // , const char *
+#define H_NEXT_EVENT 15 // , const int
+#define H_PREV_EVENT 16 // , const int
+#define H_LOAD 17 // , const char *
+#define H_SAVE 18 // , const char *
+#define H_CLEAR 19 // , void
+#define H_SETUNIQUE 20 // , int
+#define H_GETUNIQUE 21 // , void
+#define H_DEL 22 // , int
+
+struct EditLine
+{
+};
+
+struct LineInfo
+{
+ const char *buffer;
+ const char *cursor;
+ const char *lastchar;
+};
+
+struct History
+{
+};
+
+struct HistEvent
+{
+ int num;
+ const char *str;
+};
+
+extern "C"
+{
+ // edit line API
+ EditLine *el_init ( const char *, FILE *, FILE *, FILE * );
+ const char *el_gets ( EditLine *, int * );
+ int el_set ( EditLine *, int, ... );
+
+ void el_end ( EditLine * );
+ void el_reset ( EditLine * );
+ int el_getc ( EditLine *, char * );
+ void el_push ( EditLine *, char * );
+ void el_beep ( EditLine * );
+ int el_parse ( EditLine *, int, const char ** );
+ int el_get ( EditLine *, int, ... );
+ int el_source ( EditLine *, const char * );
+ void el_resize ( EditLine * );
+ const LineInfo *el_line ( EditLine * );
+ int el_insertstr( EditLine *, const char * );
+ void el_deletestr( EditLine *, int );
+
+ // history API
+ History *history_init( void );
+ void history_end ( History * );
+ int history ( History *, HistEvent *, int, ... );
+}; \ No newline at end of file
diff --git a/tools/driver/GetOptWrapper.cpp b/tools/driver/GetOptWrapper.cpp
new file mode 100644
index 000000000000..e7cdfd786c6e
--- /dev/null
+++ b/tools/driver/GetOptWrapper.cpp
@@ -0,0 +1,33 @@
+//===-- GetOptWrapper.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// this file is only relevant for Visual C++
+#if defined( _MSC_VER )
+
+#include "GetOptWrapper.h"
+
+/*
+
+// already defined in lldbHostCommon.lib due to 'getopt.inc'
+
+extern int
+getopt_long_only
+(
+ int ___argc,
+ char *const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts,
+ int *__longind
+)
+{
+ return -1;
+}
+*/
+
+#endif \ No newline at end of file
diff --git a/tools/driver/GetOptWrapper.h b/tools/driver/GetOptWrapper.h
new file mode 100644
index 000000000000..9c9cf03d7626
--- /dev/null
+++ b/tools/driver/GetOptWrapper.h
@@ -0,0 +1,49 @@
+//===-- GetOptWrapper.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_GetOptWrapper_h_
+#define lldb_GetOptWrapper_h_
+
+// from getopt.h
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+// defined int unistd.h
+extern int optreset;
+
+// from getopt.h
+extern char *optarg;
+extern int optind;
+extern int opterr;
+extern int optopt;
+
+// option structure
+struct option
+{
+ const char *name;
+ // has_arg can't be an enum because some compilers complain about
+ // type mismatches in all the code that assumes it is an int.
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+//
+extern int
+getopt_long_only
+(
+ int ___argc,
+ char *const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts,
+ int *__longind
+);
+
+#endif // lldb_GetOptWrapper_h_ \ No newline at end of file
diff --git a/tools/driver/IOChannel.cpp b/tools/driver/IOChannel.cpp
index 7adf2e4e85e9..7cba73aaae8c 100644
--- a/tools/driver/IOChannel.cpp
+++ b/tools/driver/IOChannel.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "Platform.h"
#include "IOChannel.h"
#include <map>
@@ -73,7 +74,8 @@ void
IOChannel::EraseCharsBeforeCursor ()
{
const LineInfo *line_info = el_line(m_edit_line);
- el_deletestr(m_edit_line, line_info->cursor - line_info->buffer);
+ if (line_info != NULL)
+ el_deletestr(m_edit_line, line_info->cursor - line_info->buffer);
}
unsigned char
@@ -205,6 +207,7 @@ IOChannel::IOChannel
m_read_thread_should_exit (false),
m_out_file (out),
m_err_file (err),
+ m_editline_out (editline_out),
m_command_queue (),
m_completion_key ("\t"),
m_edit_line (::el_init (SBHostOS::GetProgramFileSpec().GetFilename(), editline_in, editline_out, editline_out)),
@@ -212,50 +215,35 @@ IOChannel::IOChannel
m_history_event(),
m_getting_command (false),
m_expecting_prompt (false),
- m_prompt_str (),
+ m_prompt_str (),
m_refresh_request_pending (false)
{
assert (m_edit_line);
- ::el_set (m_edit_line, EL_PROMPT, el_prompt);
- ::el_set (m_edit_line, EL_EDITOR, "emacs");
- ::el_set (m_edit_line, EL_HIST, history, m_history);
-
- el_set (m_edit_line, EL_ADDFN, "lldb_complete",
- "LLDB completion function",
- IOChannel::ElCompletionFn);
+ el_set (m_edit_line, EL_PROMPT, el_prompt);
+ el_set (m_edit_line, EL_EDITOR, "emacs");
+ el_set (m_edit_line, EL_HIST, history, m_history);
+ el_set (m_edit_line, EL_ADDFN, "lldb_complete", "LLDB completion function", IOChannel::ElCompletionFn);
el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL);
el_set (m_edit_line, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string
el_set (m_edit_line, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does.
- el_set (m_edit_line, EL_BIND, "\e[3~", "ed-delete-next-char", NULL); // Fix the delete key.
+ el_set (m_edit_line, EL_BIND, "\033[3~", "ed-delete-next-char", NULL); // Fix the delete key.
el_set (m_edit_line, EL_CLIENTDATA, this);
// Source $PWD/.editrc then $HOME/.editrc
- ::el_source (m_edit_line, NULL);
+ el_source (m_edit_line, NULL);
assert (m_history);
- ::history (m_history, &m_history_event, H_SETSIZE, 800);
- ::history (m_history, &m_history_event, H_SETUNIQUE, 1);
+ history (m_history, &m_history_event, H_SETSIZE, 800);
+ history (m_history, &m_history_event, H_SETUNIQUE, 1);
// Load history
HistorySaveLoad (false);
- // Set up mutex to make sure OutErr, OutWrite and RefreshPrompt do not interfere
- // with each other when writing.
-
- int error;
- ::pthread_mutexattr_t attr;
- error = ::pthread_mutexattr_init (&attr);
- assert (error == 0);
- error = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
- assert (error == 0);
- error = ::pthread_mutex_init (&m_output_mutex, &attr);
- assert (error == 0);
- error = ::pthread_mutexattr_destroy (&attr);
- assert (error == 0);
-
// Initialize time that ::el_gets was last called.
-
m_enter_elgets_time.tv_sec = 0;
m_enter_elgets_time.tv_usec = 0;
+
+ // set the initial state to non flushed
+ m_output_flushed = false;
}
IOChannel::~IOChannel ()
@@ -274,8 +262,6 @@ IOChannel::~IOChannel ()
::el_end (m_edit_line);
m_edit_line = NULL;
}
-
- ::pthread_mutex_destroy (&m_output_mutex);
}
void
@@ -299,16 +285,24 @@ IOChannel::HistorySaveLoad (bool save)
void
IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len)
{
- // Make this a member variable.
- // static std::string prompt_str;
IOChannel *io_channel = (IOChannel *) baton;
- IOLocker locker (io_channel->m_output_mutex);
+ std::lock_guard<std::recursive_mutex> locker(io_channel->m_output_mutex);
const char *bytes = (const char *) src;
+ bool flush = false;
+
+ // See if we have a 'flush' synchronization point in there.
+ // this is performed from 'fputc ('\0', m_editline_out);' in LibeditGetInput()
+ if (src_len > 0 && bytes[src_len-1] == '\0')
+ {
+ src_len--;
+ flush = true;
+ }
+
if (io_channel->IsGettingCommand() && io_channel->m_expecting_prompt)
{
io_channel->m_prompt_str.append (bytes, src_len);
- // Log this to make sure the prompt is really what you think it is.
+ // Log this to make sure the prompt is really what you think it is.
if (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == 0)
{
io_channel->m_expecting_prompt = false;
@@ -327,6 +321,15 @@ IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_
io_channel->m_refresh_request_pending = false;
io_channel->OutWrite (bytes, src_len, NO_ASYNC);
}
+
+#if !defined (_MSC_VER)
+ if (flush)
+ {
+ io_channel->m_output_flushed = true;
+ io_channel->m_output_cond.notify_all();
+ }
+#endif
+
}
IOChannel::LibeditGetInputResult
@@ -344,7 +347,28 @@ IOChannel::LibeditGetInput (std::string &new_line)
// Call el_gets to prompt the user and read the user's input.
const char *line = ::el_gets (m_edit_line, &line_len);
-
+
+#if !defined (_MSC_VER)
+ // Force the piped output from el_gets to finish processing.
+ // el_gets does an fflush internally, which is not sufficient here; it only
+ // writes the data into m_editline_out, but doesn't affect whether our worker
+ // thread will read that data yet. So we block here manually.
+ {
+ std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
+ m_output_flushed = false;
+
+ // Write a synchronization point into the stream, so we can guarantee
+ // LibeditOutputBytesReceived has processed everything up till that mark.
+ fputc ('\0', m_editline_out);
+
+ while (!m_output_flushed)
+ {
+ // wait until the condition variable is signaled
+ m_output_cond.wait(m_output_mutex);
+ }
+ }
+#endif
+
// Re-set the boolean indicating whether or not el_gets is trying to get input.
SetGettingCommand (false);
@@ -379,7 +403,7 @@ IOChannel::LibeditGetInput (std::string &new_line)
return retval;
}
-void *
+thread_result_t
IOChannel::IOReadThread (void *ptr)
{
IOChannel *myself = static_cast<IOChannel *> (ptr);
@@ -502,8 +526,7 @@ IOChannel::Start ()
if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
return true;
- m_read_thread = SBHostOS::ThreadCreate ("<lldb.driver.commandline_io>", IOChannel::IOReadThread, this,
- NULL);
+ m_read_thread = SBHostOS::ThreadCreate("<lldb.driver.commandline_io>", (lldb::thread_func_t) IOChannel::IOReadThread, this, NULL);
return (IS_VALID_LLDB_HOST_THREAD(m_read_thread));
}
@@ -531,11 +554,11 @@ IOChannel::RefreshPrompt ()
{
// If we are not in the middle of getting input from the user, there is no need to
// refresh the prompt.
- IOLocker locker (m_output_mutex);
+ std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
if (! IsGettingCommand())
return;
- // If we haven't finished writing the prompt, there's no need to refresh it.
+ // If we haven't finished writing the prompt, there's no need to refresh it.
if (m_expecting_prompt)
return;
@@ -562,7 +585,7 @@ IOChannel::OutWrite (const char *buffer, size_t len, bool asynchronous)
}
// Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
- IOLocker locker (m_output_mutex);
+ std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
if (m_driver->EditlineReaderIsTop() && asynchronous)
::fwrite (undo_prompt_string, 1, 4, m_out_file);
::fwrite (buffer, 1, len, m_out_file);
@@ -577,7 +600,7 @@ IOChannel::ErrWrite (const char *buffer, size_t len, bool asynchronous)
return;
// Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
- IOLocker locker (m_output_mutex);
+ std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
if (asynchronous)
::fwrite (undo_prompt_string, 1, 4, m_err_file);
::fwrite (buffer, 1, len, m_err_file);
@@ -631,17 +654,3 @@ IOChannel::SetGettingCommand (bool new_value)
{
m_getting_command = new_value;
}
-
-IOLocker::IOLocker (pthread_mutex_t &mutex) :
- m_mutex_ptr (&mutex)
-{
- if (m_mutex_ptr)
- ::pthread_mutex_lock (m_mutex_ptr);
-
-}
-
-IOLocker::~IOLocker ()
-{
- if (m_mutex_ptr)
- ::pthread_mutex_unlock (m_mutex_ptr);
-}
diff --git a/tools/driver/IOChannel.h b/tools/driver/IOChannel.h
index 36653a0c289f..3788673da972 100644
--- a/tools/driver/IOChannel.h
+++ b/tools/driver/IOChannel.h
@@ -10,18 +10,13 @@
#ifndef lldb_IOChannel_h_
#define lldb_IOChannel_h_
+#include <thread>
+#include <mutex>
+#include <atomic>
+#include <condition_variable>
+
#include <string>
#include <queue>
-
-#if defined(__FreeBSD__)
-#include <readline/readline.h>
-#else
-#include <editline/readline.h>
-#endif
-#include <histedit.h>
-#include <pthread.h>
-#include <sys/time.h>
-
#include "Driver.h"
class IOChannel : public lldb::SBBroadcaster
@@ -63,7 +58,7 @@ public:
bool
Stop ();
- static void *
+ static lldb::thread_result_t
IOReadThread (void *);
void
@@ -127,7 +122,8 @@ protected:
private:
- pthread_mutex_t m_output_mutex;
+ std::recursive_mutex m_output_mutex;
+ std::condition_variable_any m_output_cond;
struct timeval m_enter_elgets_time;
Driver *m_driver;
@@ -135,6 +131,7 @@ private:
bool m_read_thread_should_exit;
FILE *m_out_file;
FILE *m_err_file;
+ FILE *m_editline_out;
std::queue<std::string> m_command_queue;
const char *m_completion_key;
@@ -143,7 +140,8 @@ private:
HistEvent m_history_event;
bool m_getting_command;
bool m_expecting_prompt;
- std::string m_prompt_str; // for accumlating the prompt as it gets written out by editline
+ bool m_output_flushed;
+ std::string m_prompt_str; // for accumlating the prompt as it gets written out by editline
bool m_refresh_request_pending;
void
@@ -153,22 +151,4 @@ private:
HandleCompletion (EditLine *e, int ch);
};
-class IOLocker
-{
-public:
-
- IOLocker (pthread_mutex_t &mutex);
-
- ~IOLocker ();
-
-protected:
-
- pthread_mutex_t *m_mutex_ptr;
-
-private:
-
- IOLocker (const IOLocker&);
- const IOLocker& operator= (const IOLocker&);
-};
-
#endif // lldb_IOChannel_h_
diff --git a/tools/driver/Platform.cpp b/tools/driver/Platform.cpp
new file mode 100644
index 000000000000..5b5286e68114
--- /dev/null
+++ b/tools/driver/Platform.cpp
@@ -0,0 +1,111 @@
+//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// this file is only relevant for Visual C++
+#if defined( _MSC_VER )
+
+#include <process.h>
+#include <assert.h>
+
+#include "Platform.h"
+
+// index one of the variable arguments
+// presuming "(EditLine *el, ..." is first in the argument list
+#define GETARG( Y, X ) ( (void* ) *( ( (int**) &(Y) ) + (X) ) )
+
+// the control handler or SIGINT handler
+static sighandler_t _ctrlHandler = NULL;
+
+// the default console control handler
+BOOL
+WINAPI CtrlHandler (DWORD ctrlType)
+{
+ if ( _ctrlHandler != NULL )
+ {
+ _ctrlHandler( 0 );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int
+ioctl (int d, int request, ...)
+{
+ switch ( request )
+ {
+ // request the console windows size
+ case ( TIOCGWINSZ ):
+ {
+ // locate the window size structure on stack
+ winsize *ws = (winsize*) GETARG( d, 2 );
+ // get screen buffer information
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &info );
+ // fill in the columns
+ ws->ws_col = info.dwMaximumWindowSize.X;
+ //
+ return 0;
+ }
+ break;
+ default:
+ assert( !"Not implemented!" );
+ }
+ return -1;
+}
+
+int
+kill (pid_t pid, int sig)
+{
+ // is the app trying to kill itself
+ if ( pid == getpid( ) )
+ exit( sig );
+ //
+ assert( !"Not implemented!" );
+ return -1;
+}
+
+int
+tcsetattr (int fd, int optional_actions, const struct termios *termios_p)
+{
+ assert( !"Not implemented!" );
+ return -1;
+}
+
+int
+tcgetattr (int fildes, struct termios *termios_p)
+{
+// assert( !"Not implemented!" );
+ // error return value (0=success)
+ return -1;
+}
+
+sighandler_t
+signal (int sig, sighandler_t sigFunc)
+{
+ switch ( sig )
+ {
+ case ( SIGINT ):
+ {
+ _ctrlHandler = sigFunc;
+ SetConsoleCtrlHandler( CtrlHandler, TRUE );
+ }
+ break;
+ case ( SIGPIPE ):
+ case ( SIGWINCH ):
+ case ( SIGTSTP ):
+ case ( SIGCONT ):
+ // ignore these for now
+ break;
+ default:
+ assert( !"Not implemented!" );
+ }
+ return 0;
+}
+
+#endif \ No newline at end of file
diff --git a/tools/driver/Platform.h b/tools/driver/Platform.h
new file mode 100644
index 000000000000..f1fe1e4aac18
--- /dev/null
+++ b/tools/driver/Platform.h
@@ -0,0 +1,113 @@
+//===-- Platform.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_Platform_h_
+#define lldb_Platform_h_
+
+#if defined( _MSC_VER )
+
+ // this will stop signal.h being included
+ #define _INC_SIGNAL
+
+ #include <io.h>
+ #include <eh.h>
+ #include <inttypes.h>
+ #include "ELWrapper.h"
+ #include "lldb/Host/windows/Windows.h"
+ #include "GetOptWrapper.h"
+
+ struct timeval
+ {
+ long tv_sec;
+ long tv_usec;
+ };
+
+ struct winsize
+ {
+ long ws_col;
+ };
+
+ typedef unsigned char cc_t;
+ typedef unsigned int speed_t;
+ typedef unsigned int tcflag_t;
+
+ // fcntl.h
+ #define O_NOCTTY 0400
+
+ // ioctls.h
+ #define TIOCGWINSZ 0x5413
+
+ // signal.h
+ #define SIGPIPE 13
+ #define SIGCONT 18
+ #define SIGTSTP 20
+ #define SIGWINCH 28
+
+ // tcsetattr arguments
+ #define TCSANOW 0
+
+ #define NCCS 32
+ struct termios
+ {
+ tcflag_t c_iflag; // input mode flags
+ tcflag_t c_oflag; // output mode flags
+ tcflag_t c_cflag; // control mode flags
+ tcflag_t c_lflag; // local mode flags
+ cc_t c_line; // line discipline
+ cc_t c_cc[NCCS]; // control characters
+ speed_t c_ispeed; // input speed
+ speed_t c_ospeed; // output speed
+ };
+
+ typedef long pid_t;
+
+ #define STDIN_FILENO 0
+
+ #define PATH_MAX MAX_PATH
+ #define snprintf _snprintf
+
+ extern int ioctl( int d, int request, ... );
+ extern int kill ( pid_t pid, int sig );
+ extern int tcsetattr( int fd, int optional_actions, const struct termios *termios_p );
+ extern int tcgetattr( int fildes, struct termios *termios_p );
+
+ // signal handler function pointer type
+ typedef void (*sighandler_t)(int);
+
+ // signal.h
+ #define SIGINT 2
+ // default handler
+ #define SIG_DFL ( (sighandler_t) -1 )
+ // ignored
+ #define SIG_IGN ( (sighandler_t) -2 )
+ extern sighandler_t signal( int sig, sighandler_t );
+
+#else
+
+ #include <inttypes.h>
+
+ #include <getopt.h>
+ #include <libgen.h>
+ #include <sys/ioctl.h>
+ #include <termios.h>
+ #include <unistd.h>
+
+ #include <histedit.h>
+ #include <pthread.h>
+ #include <sys/time.h>
+
+ #if defined(__FreeBSD__)
+ #include <readline/readline.h>
+ #else
+ #include <editline/readline.h>
+ #endif
+
+#endif
+
+#endif // lldb_Platform_h_
diff --git a/tools/lldb-platform/lldb-platform.cpp b/tools/lldb-platform/lldb-platform.cpp
new file mode 100644
index 000000000000..007e69c92814
--- /dev/null
+++ b/tools/lldb-platform/lldb-platform.cpp
@@ -0,0 +1,270 @@
+//===-- lldb-platform.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"
+
+// C Includes
+#include <errno.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// C++ Includes
+
+// Other libraries and framework includes
+#include "lldb/Core/Error.h"
+#include "lldb/Core/ConnectionFileDescriptor.h"
+#include "lldb/Core/ConnectionMachPort.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/StreamFile.h"
+#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
+#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// option descriptors for getopt_long_only()
+//----------------------------------------------------------------------
+
+int g_debug = 0;
+int g_verbose = 0;
+int g_stay_alive = 0;
+
+static struct option g_long_options[] =
+{
+ { "debug", no_argument, &g_debug, 1 },
+ { "verbose", no_argument, &g_verbose, 1 },
+ { "stay-alive", no_argument, &g_stay_alive, 1 },
+ { "log-file", required_argument, NULL, 'l' },
+ { "log-flags", required_argument, NULL, 'f' },
+ { "listen", required_argument, NULL, 'L' },
+ { NULL, 0, NULL, 0 }
+};
+
+//----------------------------------------------------------------------
+// Watch for signals
+//----------------------------------------------------------------------
+int g_sigpipe_received = 0;
+void
+signal_handler(int signo)
+{
+ switch (signo)
+ {
+ case SIGPIPE:
+ g_sigpipe_received = 1;
+ break;
+ case SIGHUP:
+ // Use SIGINT first, if that does not work, use SIGHUP as a last resort.
+ // And we should not call exit() here because it results in the global destructors
+ // to be invoked and wreaking havoc on the threads still running.
+ Host::SystemLog(Host::eSystemLogWarning, "SIGHUP received, exiting lldb-platform...\n");
+ abort();
+ break;
+ }
+}
+
+static void
+display_usage (const char *progname)
+{
+ fprintf(stderr, "Usage:\n %s [--log-file log-file-path] [--log-flags flags] --listen port\n", progname);
+ exit(0);
+}
+
+//----------------------------------------------------------------------
+// main
+//----------------------------------------------------------------------
+int
+main (int argc, char *argv[])
+{
+ const char *progname = argv[0];
+ signal (SIGPIPE, signal_handler);
+ signal (SIGHUP, signal_handler);
+ int long_option_index = 0;
+ StreamSP log_stream_sp;
+ Args log_args;
+ Error error;
+ std::string listen_host_port;
+ int ch;
+ Debugger::Initialize();
+
+// ConnectionMachPort a;
+// ConnectionMachPort b;
+//
+// lldb::ConnectionStatus status;
+// const char *bootstrap_service_name = "HelloWorld";
+// status = a.BootstrapCheckIn(bootstrap_service_name, &error);
+//
+// if (status != eConnectionStatusSuccess)
+// {
+// fprintf(stderr, "%s", error.AsCString());
+// return 1;
+// }
+// status = b.BootstrapLookup (bootstrap_service_name, &error);
+// if (status != eConnectionStatusSuccess)
+// {
+// fprintf(stderr, "%s", error.AsCString());
+// return 2;
+// }
+//
+// if (a.Write ("hello", 5, status, &error) == 5)
+// {
+// char buf[32];
+// memset(buf, 0, sizeof(buf));
+// if (b.Read (buf, 5, status, &error))
+// {
+// printf("read returned bytes: %s", buf);
+// }
+// else
+// {
+// fprintf(stderr, "%s", error.AsCString());
+// return 4;
+// }
+// }
+// else
+// {
+// fprintf(stderr, "%s", error.AsCString());
+// return 3;
+// }
+
+ while ((ch = getopt_long_only(argc, argv, "l:f:L:", g_long_options, &long_option_index)) != -1)
+ {
+// DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
+// ch, (uint8_t)ch,
+// g_long_options[long_option_index].name,
+// g_long_options[long_option_index].has_arg ? '=' : ' ',
+// optarg ? optarg : "");
+ switch (ch)
+ {
+ case 0: // Any optional that auto set themselves will return 0
+ break;
+
+ case 'l': // Set Log File
+ if (optarg && optarg[0])
+ {
+ if ((strcasecmp(optarg, "stdout") == 0) || (strcmp(optarg, "/dev/stdout") == 0))
+ {
+ log_stream_sp.reset (new StreamFile (stdout, false));
+ }
+ else if ((strcasecmp(optarg, "stderr") == 0) || (strcmp(optarg, "/dev/stderr") == 0))
+ {
+ log_stream_sp.reset (new StreamFile (stderr, false));
+ }
+ else
+ {
+ FILE *log_file = fopen(optarg, "w");
+ if (log_file)
+ {
+ setlinebuf(log_file);
+ log_stream_sp.reset (new StreamFile (log_file, true));
+ }
+ else
+ {
+ const char *errno_str = strerror(errno);
+ fprintf (stderr, "Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error");
+ }
+
+ }
+
+ }
+ break;
+
+ case 'f': // Log Flags
+ if (optarg && optarg[0])
+ log_args.AppendArgument(optarg);
+ break;
+
+ case 'L':
+ listen_host_port.append (optarg);
+ break;
+
+ case 'h': /* fall-through is intentional */
+ case '?':
+ display_usage(progname);
+ break;
+ }
+ }
+ // Print usage and exit if no listening port is specified.
+ if (listen_host_port.empty())
+ display_usage(progname);
+
+ if (log_stream_sp)
+ {
+ if (log_args.GetArgumentCount() == 0)
+ log_args.AppendArgument("default");
+ ProcessGDBRemoteLog::EnableLog (log_stream_sp, 0,log_args.GetConstArgumentVector(), log_stream_sp.get());
+ }
+
+ // Skip any options we consumed with getopt_long_only
+ argc -= optind;
+ argv += optind;
+
+
+ do {
+ GDBRemoteCommunicationServer gdb_server (true);
+ if (!listen_host_port.empty())
+ {
+ std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
+ if (conn_ap.get())
+ {
+ for (int j = 0; j < listen_host_port.size(); j++)
+ {
+ char c = listen_host_port[j];
+ if (c > '9' || c < '0')
+ printf("WARNING: passing anything but a number as argument to --listen will most probably make connecting impossible.\n");
+ }
+ std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
+ if (conn_ap.get())
+ {
+ std::string connect_url ("listen://");
+ connect_url.append(listen_host_port.c_str());
+
+ printf ("Listening for a connection on %s...\n", listen_host_port.c_str());
+ if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
+ {
+ printf ("Connection established.\n");
+ gdb_server.SetConnection (conn_ap.release());
+ }
+ }
+ }
+
+ if (gdb_server.IsConnected())
+ {
+ // After we connected, we need to get an initial ack from...
+ if (gdb_server.HandshakeWithClient(&error))
+ {
+ bool interrupt = false;
+ bool done = false;
+ while (!interrupt && !done)
+ {
+ if (!gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done))
+ break;
+ }
+
+ if (error.Fail())
+ {
+ fprintf(stderr, "error: %s\n", error.AsCString());
+ }
+ }
+ else
+ {
+ fprintf(stderr, "error: handshake with client failed\n");
+ }
+ }
+ }
+ } while (g_stay_alive);
+
+ Debugger::Terminate();
+
+ fprintf(stderr, "lldb-platform exiting...\n");
+
+ return 0;
+}